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

merge actual develop

parents 0e5dd9ee 7db1a09f
...@@ -13,3 +13,10 @@ ...@@ -13,3 +13,10 @@
/captures /captures
.externalNativeBuild .externalNativeBuild
.cxx .cxx
/app/libs
/app/src/main/assets
/app/src/main/jniLibs
/app/release
...@@ -10,14 +10,28 @@ apply from: '../dependencies.gradle' ...@@ -10,14 +10,28 @@ apply from: '../dependencies.gradle'
apply plugin: 'kotlinx-serialization' apply plugin: 'kotlinx-serialization'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
//apply plugin: 'io.fabric' //apply plugin: 'io.fabric'
// Create a variable called keystorePropertiesFile, and initialize it to your
// keystore.properties file, in the rootProject folder.
// Initialize a new Properties() object called keystoreProperties.
def keystoreProperties = new Properties()
// Load your keystore.properties file into the keystoreProperties object.
android { android {
compileSdkVersion compileSdkVersion_RoomPark compileSdkVersion compileSdkVersion_RoomPark
defaultConfig { defaultConfig {
applicationId $APPLICATION_ID applicationId $APPLICATION_ID
ndk { ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86' abiFilters 'armeabi-v7a', 'arm64-v8a'
} }
minSdkVersion minSdkVersion_RoomPark minSdkVersion minSdkVersion_RoomPark
targetSdkVersion targetSdkVersion_RoomPark targetSdkVersion targetSdkVersion_RoomPark
...@@ -26,19 +40,57 @@ android { ...@@ -26,19 +40,57 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
signingConfigs {
release {
def keystorePropertiesFile = rootProject.file("../roomParkKeystore.properties")
if ( keystorePropertiesFile.exists() ){
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
// else throw new GradleException('Plesase, provide keystore properties file! ')
// You need to specify either an absolute path or include the
// keystore file in the same directory as the build.gradle file.
}
}
buildTypes { buildTypes {
debug { debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
aaptOptions.cruncherEnabled = false aaptOptions.cruncherEnabled = false
ext.alwaysUpdateBuildId = false ext.alwaysUpdateBuildId = false
} }
release { release {
minifyEnabled false signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
debuggable false debuggable false
} }
} }
aaptOptions {
noCompress '.unity3d', '.ress', '.resource', '.obb'
}
task renameBundle(type: Copy) {
from "$buildDir/outputs/bundle/release"
into "../../"
String name = findProperty('newBundleName')
rename 'app-release.aab', "${name}.aab"
}
task publishRelease(type: GradleBuild) {
tasks = ['bundleRelease']
}
androidExtensions { androidExtensions {
experimental = true experimental = true
} }
...@@ -56,6 +108,10 @@ android { ...@@ -56,6 +108,10 @@ android {
targetCompatibility 1.8 targetCompatibility 1.8
sourceCompatibility 1.8 sourceCompatibility 1.8
} }
lintOptions {
disable 'BinaryOperationInTimber'
}
} }
kapt { kapt {
...@@ -80,11 +136,6 @@ dependencies { ...@@ -80,11 +136,6 @@ dependencies {
//Logger: Timber //Logger: Timber
implementation "com.jakewharton.timber:timber:$timberVersion" implementation "com.jakewharton.timber:timber:$timberVersion"
//Crashlytics
implementation('com.crashlytics.sdk.android:crashlytics:2.10.0@aar') {
transitive = true;
}
//RxJava //RxJava
implementation "io.reactivex.rxjava3:rxjava:$rxJavaVersion" implementation "io.reactivex.rxjava3:rxjava:$rxJavaVersion"
...@@ -162,6 +213,19 @@ dependencies { ...@@ -162,6 +213,19 @@ dependencies {
implementation 'jp.wasabeef:glide-transformations:4.0.0' implementation 'jp.wasabeef:glide-transformations:4.0.0'
kapt "com.github.bumptech.glide:compiler:$glideVersion" kapt "com.github.bumptech.glide:compiler:$glideVersion"
//Firebase
implementation "com.google.firebase:firebase-analytics:$fireBaseVersion"
implementation 'com.google.firebase:firebase-messaging:20.1.3'
//CrshLytics
implementation "com.google.firebase:firebase-crashlytics:$firebaseCrashlyticsVersion"
//RxKotlin
implementation("io.reactivex.rxjava2:rxkotlin:$rxKotlinVersion")
//Arch Lifecycle
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
//Tests //Tests
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:runner:1.2.0'
......
{
"project_info": {
"project_number": "740988198336",
"firebase_url": "https://room-park-9cc38.firebaseio.com",
"project_id": "room-park-9cc38",
"storage_bucket": "room-park-9cc38.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:740988198336:android:0fd03bfcfa85b78dae3c25",
"android_client_info": {
"package_name": "com.biganto.visual.roompark"
}
},
"oauth_client": [
{
"client_id": "740988198336-e2vel467jbici47mkokmmtuhg07gfl8k.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.biganto.visual.roompark",
"certificate_hash": "f23a8c722c050ddb5e6015b9f254535ddf5387ff"
}
},
{
"client_id": "740988198336-8c08r8mikgulg2s08p0fgi5j028rhn4u.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBvrvu2Iz2FGEf7S_DVaSwQmhuijIuW2SU"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "740988198336-8c08r8mikgulg2s08p0fgi5j028rhn4u.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}
\ No newline at end of file
...@@ -19,3 +19,202 @@ ...@@ -19,3 +19,202 @@
# If you keep the line number information, uncomment this to # If you keep the line number information, uncomment this to
# hide the original source file name. # hide the original source file name.
#-renamesourcefileattribute SourceFile #-renamesourcefileattribute SourceFile
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
}
-dontwarn com.franmontiel.persistentcookiejar.**
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-dontwarn com.google.vr.ndk.base.DaydreamAp
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
# prevent Crashlytics obfuscation
-dontwarn com.crashlytics.**
-dontwarn org.kobjects.**
-dontwarn org.ksoap2.**
-dontwarn org.kxml2.**
-dontwarn org.xmlpull.v1.**
-keep class com.biganto.visual.roompark.data.repository.db.requrey.model** { *; }
-keep class com.biganto.visual.roompark.player.unity_utils** { *; }
-keepclassmembers class com.biganto.visual.roompark.player.unity_utils** { *; }
-keep class com.biganto.visual.roompark.player.BigantoPlayerActivity { *; }
-keepclassmembers class com.biganto.visual.roompark.player.BigantoPlayerActivity** { *; }
-keep public class * implements android.os.Parcelable
# keep CREATOR for referenced parcelables since it is accessed via reflection
-keepclassmembers class * implements android.os.Parcelable {
static ** CREATOR;
}
-dontobfuscate -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
# could be refined, but if it works you got the idea
-keepnames class * implements android.os.Parcelable { *; }
-keepclassmembers class * implements android.os.Parcelable { *; }
-keepnames class * implements com.bluelinelabs.conductor** { *; }
-keepclassmembers class * implements com.bluelinelabs.conductor** { *; }
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keep class com.biganto.visual.roompark.data.repository.api.biganto.raw** { *; }
-keepclassmembers class com.biganto.visual.roompark.data.repository.api.biganto.raw** { *; }
-keep class com.biganto.visual.roompark.data.repository.api.room_park.raw** { *; }
-keepclassmembers class com.biganto.visual.roompark.data.repository.api.room_park.raw** { *; }
# prevent Requery obfuscation
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontoptimize
-dontpreverify
-dontwarn java.lang.FunctionalInterface
-dontwarn java.util.**
-dontwarn java.time.**
-dontwarn javax.annotation.**
-dontwarn javax.cache.**
-dontwarn javax.naming.**
-dontwarn javax.transaction.**
-dontwarn java.sql.**
-dontwarn javax.sql.**
-dontwarn androidx.**
-dontwarn io.requery.cache.**
-dontwarn io.requery.rx.**
-dontwarn io.requery.reactivex.**
-dontwarn io.requery.reactor.**
-dontwarn io.requery.query.**
-dontwarn io.requery.android.sqlcipher.**
-dontwarn io.requery.android.sqlitex.**
-keepclassmembers enum io.requery** {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# google vr sdk
# Don't obfuscate any NDK/SDK code. This makes the debugging of stack traces
# in release builds easier.
-keepnames class com.google.vr.ndk** { *; }
-keepnames class com.google.vr.sdk** { *; }
# These are part of the Java <-> native interfaces for GVR.
-keepclasseswithmembernames,includedescriptorclasses class com.google.vr** {
native <methods>;
}
# The SDK configuration protos use reflection.
-keep class com.google.vr.sdk.proto** {
*;
}
-keep class com.google.common.logging.Vr$VREvent$SdkConfigurationParams** {
*;
}
-keep class com.google.common.logging.nano.Vr$VREvent$SdkConfigurationParams** {
*;
}
-keep class com.google.vr.cardboard.UsedByNative
-keep @com.google.vr.cardboard.UsedByNative class *
-keepclassmembers class * {
@com.google.vr.cardboard.UsedByNative *;
}
-keep class com.google.vr.cardboard.annotations.UsedByNative
-keep @com.google.vr.cardboard.annotations.UsedByNative class *
-keepclassmembers class * {
@com.google.vr.cardboard.annotations.UsedByNative *;
}
-keep class com.google.vr.cardboard.annotations.UsedByReflection
-keep @com.google.vr.cardboard.annotations.UsedByReflection class *
-keepclassmembers class * {
@com.google.vr.cardboard.annotations.UsedByReflection *;
}
-dontwarn sun.misc.Unsafe
-dontwarn libcore.io.Memory
# end googlevr sdk
-dontusemixedcaseclassnames
-dontwarn android.support.**
-verbose
-dontoptimize
-dontpreverify
-keep class com.unity3d** { *; }
-keep class org.fmod** { *; }
-keep class bitter.jnibridge** { *; }
-keepclassmembers class com.tms.rarus.videoserver.* { *; }
-keepclassmembers class com.unity3d.player** { *; }
-keepclassmembers class org.fmod** { *; }
-keepclasseswithmembernames class * {
native <methods>;
}
-keep class com.google.firebase.crashlytics** { *; }
-dontwarn com.google.firebase.crashlytics.**
-keep class com.google.android.gms** { *; }
-dontwarn com.google.android.gms.**
-keep class com.biganto.androidplayer** { *; }
-keepclassmembers class com.biganto.androidplayer.* { *; }
-libraryjars ./libs/unity-classes.jar
#-libraryjars ./libs/libprotobuf-java-nano.jar
-keep interface kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader
-keep class kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl
-keep class com.biganto.visual.roompark.presentation.screen.settings.util** { *; }
-keepclassmembers class com.biganto.visual.roompark.presentation.screen.settings.util** { *; }
-dontwarn kotlin.reflect.jvm.internal.**
-keep class kotlin** {
public protected *;
}
-keepclassmembers class * { public <init>(...); }
\ No newline at end of file
...@@ -2,19 +2,26 @@ ...@@ -2,19 +2,26 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.biganto.visual.roompark"> 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.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:name=".base.RoomParkApplication" android:name=".base.RoomParkApplication"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:screenOrientation="userPortrait"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.Launch"> android:theme="@style/AppTheme.Launch">
<activity android:name=".base.RoomParkMainActivity" <activity
android:name=".base.RoomParkMainActivity"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustPan"> android:windowSoftInputMode="stateHidden|adjustPan">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
...@@ -22,6 +29,47 @@ ...@@ -22,6 +29,47 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".player.BigantoPlayerActivity" android:screenOrientation="fullSensor"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
android:largeHeap="true"
android:hardwareAccelerated="true"
android:process=":UnityKillsMe">
</activity>
<service
android:name=".data.RoomParkMessageService"
android:enabled="true"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
<!--
Set custom default icon. This is used when no icon is set for incoming notification messages.
See README(https://goo.gl/l4GJaQ) for more.-->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_bell_on" />
<!--
Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. See README(https://goo.gl/6BKBk7) for more.
-->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />
</service>
<service
android:name=".data.service.download.DownloadManagerService"
android:enabled="true"
android:exported="false" />
</application> </application>
</manifest> </manifest>
\ No newline at end of file
...@@ -4,10 +4,13 @@ import android.util.Log ...@@ -4,10 +4,13 @@ import android.util.Log
import com.biganto.visual.roompark.BuildConfig import com.biganto.visual.roompark.BuildConfig
import com.biganto.visual.roompark.di.dagger.AppComponent import com.biganto.visual.roompark.di.dagger.AppComponent
import com.biganto.visual.roompark.di.dagger.DaggerAppComponent import com.biganto.visual.roompark.di.dagger.DaggerAppComponent
import com.crashlytics.android.Crashlytics
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.DaggerApplication import dagger.android.DaggerApplication
import io.reactivex.exceptions.UndeliverableException
import io.reactivex.plugins.RxJavaPlugins
import kotlinx.io.IOException
import timber.log.Timber import timber.log.Timber
import java.net.SocketException
/** /**
* Created by Vladislav Bogdashkin on 03.09.2019. * Created by Vladislav Bogdashkin on 03.09.2019.
...@@ -34,15 +37,46 @@ class RoomParkApplication : DaggerApplication() { ...@@ -34,15 +37,46 @@ class RoomParkApplication : DaggerApplication() {
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree()) if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
else Timber.plant(CrashlyticsTree()) else Timber.plant(CrashlyticsTree())
RxJavaPlugins.setErrorHandler { e ->
when (e) {
is UndeliverableException -> {
}
// fine, irrelevant network problem or API that throws on cancellation
is IOException -> return@setErrorHandler
is SocketException -> return@setErrorHandler
// fine, some blocking code was interrupted by a dispose call
is InterruptedException ->
return@setErrorHandler
// that's likely a bug in the application
is NullPointerException -> {
Thread.currentThread().uncaughtExceptionHandler
.uncaughtException(Thread.currentThread(), e)
return@setErrorHandler
}
is IllegalArgumentException -> {
Thread.currentThread().uncaughtExceptionHandler
.uncaughtException(Thread.currentThread(), e)
return@setErrorHandler
}
// that's a bug in RxJava or in a custom operator
is IllegalStateException -> {
Thread.currentThread().uncaughtExceptionHandler
.uncaughtException(Thread.currentThread(), e)
return@setErrorHandler
} }
}
Timber.w(e, "Undeliverable exception received, not sure what to do")
}
}
} }
private class CrashlyticsTree : Timber.Tree() { private class CrashlyticsTree : Timber.Tree() {
override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) { override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) {
if (priority == Log.VERBOSE || priority == Log.DEBUG) return if (priority == Log.VERBOSE || priority == Log.DEBUG) return
Crashlytics.log(priority, tag, message)
throwable?.let { Crashlytics.logException(it) }
} }
} }
\ No newline at end of file
...@@ -9,7 +9,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout ...@@ -9,7 +9,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.isGone import androidx.core.view.isGone
import butterknife.BindView import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import com.biganto.visual.roompark.BuildConfig
import com.biganto.visual.roompark.R import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.presentation.screen.splash.SplashScreenController import com.biganto.visual.roompark.presentation.screen.splash.SplashScreenController
import com.biganto.visual.roompark.util.extensions.setGone import com.biganto.visual.roompark.util.extensions.setGone
...@@ -17,12 +16,11 @@ import com.biganto.visual.roompark.util.view_utils.app_bar.DragControlAppBarLayo ...@@ -17,12 +16,11 @@ import com.biganto.visual.roompark.util.view_utils.app_bar.DragControlAppBarLayo
import com.bluelinelabs.conductor.Conductor import com.bluelinelabs.conductor.Conductor
import com.bluelinelabs.conductor.Router import com.bluelinelabs.conductor.Router
import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.RouterTransaction
import com.crashlytics.android.Crashlytics
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.textview.MaterialTextView import com.google.android.material.textview.MaterialTextView
import io.fabric.sdk.android.Fabric
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.bell_switch_view.view.*
import kotlinx.android.synthetic.main.status_layout_toolbar.view.* import kotlinx.android.synthetic.main.status_layout_toolbar.view.*
import kotlinx.android.synthetic.main.switch_toolbar.view.* import kotlinx.android.synthetic.main.switch_toolbar.view.*
import timber.log.Timber import timber.log.Timber
...@@ -53,7 +51,7 @@ class RoomParkMainActivity( ...@@ -53,7 +51,7 @@ class RoomParkMainActivity(
setTheme(R.style.AppTheme) setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (!BuildConfig.DEBUG) Fabric.with(this, Crashlytics()) // if (!BuildConfig.DEBUG) Fabric.with(this, Crashlytics())
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
...@@ -108,7 +106,7 @@ class RoomParkMainActivity( ...@@ -108,7 +106,7 @@ class RoomParkMainActivity(
headerToolbarBack.text = it.backTitle?:"" headerToolbarBack.text = it.backTitle?:""
headerToolbar.toolbar_title.text = it.title?:"" headerToolbar.toolbar_title.text = it.title?:""
headerToolbar.include13.setGone(!(it.switcher?:false)) headerToolbar.bell_container.setGone(!(it.switcher?:false))
} }
status?.let { status?.let {
statusToolbar.status_icon.setGone(it.state == null) statusToolbar.status_icon.setGone(it.state == null)
......
...@@ -102,6 +102,7 @@ abstract class BigantoBaseController<VS : BigantoBaseViewState,V: BigantoBaseCon ...@@ -102,6 +102,7 @@ abstract class BigantoBaseController<VS : BigantoBaseViewState,V: BigantoBaseCon
} }
override fun handleBack(): Boolean { override fun handleBack(): Boolean {
detachDisposable.clear()
router.popController(this) router.popController(this)
return true return true
// return super.handleBack() // return super.handleBack()
......
...@@ -30,12 +30,11 @@ abstract class BigantoBasePresenter<V : MvpView, VS> ...@@ -30,12 +30,11 @@ abstract class BigantoBasePresenter<V : MvpView, VS>
open fun parseError(t: Throwable) : VS = open fun parseError(t: Throwable) : VS =
when (t) { when (t) {
is CustomApiException ->{ is CustomApiException -> {
Timber.e("CustomApiException ${t.messageStringId} / ${t.customMessage}") Timber.e("CustomApiException ${t.messageStringId} / ${t.customMessage}")
parse(t) parse(t)
} }
is NoNetworkException -> {parse(t)}
is NoNetworkException -> parse(t)
else -> {Timber.e(t);parse(t)} else -> {Timber.e(t);parse(t)}
} }
......
...@@ -25,7 +25,7 @@ import timber.log.Timber ...@@ -25,7 +25,7 @@ import timber.log.Timber
* Created by Vladislav Bogdashkin on 09.04.2019. * Created by Vladislav Bogdashkin on 09.04.2019.
*/ */
internal const val PHOTOS_KEY = "CHHOSE_PHOTO_LIST_KEY" internal const val PHOTOS_KEY = "CHOOSE_PHOTO_LIST_KEY"
private fun formBundle(photos: ArrayList<PhotoResolutionModel>): Bundle { private fun formBundle(photos: ArrayList<PhotoResolutionModel>): Bundle {
val b = Bundle() val b = Bundle()
...@@ -66,7 +66,6 @@ class ChooseResolutionDialogController : Controller { ...@@ -66,7 +66,6 @@ class ChooseResolutionDialogController : Controller {
detachDisposable.add( detachDisposable.add(
(recyclerView.adapter as PhotoSizeAdapter).onItemClicked.subscribe { (recyclerView.adapter as PhotoSizeAdapter).onItemClicked.subscribe {
Timber.d("gonna shit : $it")
router.replaceTopController(RouterTransaction.with( router.replaceTopController(RouterTransaction.with(
PhotoDialogController( PhotoDialogController(
it.url it.url
......
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
}
package com.biganto.visual.roompark.conductor.dialogs package com.biganto.visual.roompark.conductor.dialogs
import android.annotation.SuppressLint
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.graphics.Bitmap import android.graphics.Bitmap
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ProgressBar import android.widget.ProgressBar
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.recyclerview.widget.RecyclerView
import com.biganto.visual.roompark.R import com.biganto.visual.roompark.R
import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.Controller
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
...@@ -20,6 +21,7 @@ import com.bumptech.glide.request.RequestListener ...@@ -20,6 +21,7 @@ import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target import com.bumptech.glide.request.target.Target
import com.github.chrisbanes.photoview.PhotoView import com.github.chrisbanes.photoview.PhotoView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import timber.log.Timber
/** /**
...@@ -35,15 +37,14 @@ class PhotoDialogController : Controller { ...@@ -35,15 +37,14 @@ class PhotoDialogController : Controller {
constructor(photoUrl: String) : super(bundleOf(PHOTO_URL_KEY to photoUrl)) constructor(photoUrl: String) : super(bundleOf(PHOTO_URL_KEY to photoUrl))
lateinit var recyclerView : RecyclerView
@SuppressLint("SourceLockedOrientationActivity")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
val view = inflater.inflate(getLayoutId(), container, false) val view = inflater.inflate(getLayoutId(), container, false)
val progress = view.findViewById<ProgressBar>(R.id.photo_load_progress_bar) val progress = view.findViewById<ProgressBar>(R.id.photo_load_progress_bar)
progress.visibility = View.VISIBLE progress.visibility = View.VISIBLE
view.findViewById<View>(R.id.close_current_button).setOnClickListener { handleBack() }
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
...@@ -79,12 +80,20 @@ class PhotoDialogController : Controller { ...@@ -79,12 +80,20 @@ class PhotoDialogController : Controller {
}) })
.into(photoView) .into(photoView)
} }
view.findViewById<ImageView>(R.id.close_current_button).setOnClickListener {
Timber.d("Clicked")
handleBack()
}
return view return view
} }
@LayoutRes @LayoutRes
fun getLayoutId() = R.layout.photo_viewer fun getLayoutId() = R.layout.photo_viewer
@SuppressLint("SourceLockedOrientationActivity")
override fun handleBack(): Boolean { override fun handleBack(): Boolean {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
return router.popCurrentController() return router.popCurrentController()
......
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.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.conductor.dialogs.change_handler.DialogChangeHandler
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.data.service.network.INetworkMonitor
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.bluelinelabs.conductor.RouterTransaction
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 TYPICAL_PLAN_SIZE = (1.2f*1024L*1024L).toLong()
class StartPlansDownloadingDialogController : Controller {
constructor() : super()
constructor(args: Bundle) : super(args)
private val detachDisposable = CompositeDisposable()
override fun onDetach(view: View) {
detachDisposable.clear()
super.onDetach(view)
}
@Inject
lateinit var interactor: SettingsInteractor
@Inject
lateinit var file: FileModule
lateinit var snackbar: ISnackBarProvider
@Inject
lateinit var rpActivity: RoomParkMainActivity
@Inject
lateinit var networkMonitor: INetworkMonitor
override fun onContextAvailable(context: Context) {
super.onContextAvailable(context)
DaggerStartPlansDownloadingDialogScreenComponent.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)
view.findViewById<MaterialTextView>(R.id.download_dialog_title)
.text = resources?.getString(R.string.download_all_plans_notice_text)
view.findViewById<MaterialTextView>(R.id.all_tours_size_textView)
.text = resources?.getString(R.string.download_all_plans_size_title
,"0")
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(
interactor.fetchPlanTypesSizes()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({
view.findViewById<MaterialTextView>(R.id.all_tours_size_textView)
.text = resources?.getString(R.string.download_all_plans_size_title
,(it* TYPICAL_PLAN_SIZE).bytesToSize())
},
{err ->
Timber.e(err)
snackbar.showSnackBar(R.string.download_all_plans_errors_snackbar_message)
})
)
detachDisposable.add(
view.findViewById<Button>(R.id.alert_ok_button)
.clicks()
.filter{
if (!networkMonitor.isConnected){
snackbar.showSnackBar(R.string.no_network_error)
}
networkMonitor.isConnected
}
.debounce(200, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
router.replaceTopController(
RouterTransaction.with(DownloadPlansDialogController())
.pushChangeHandler(DialogChangeHandler())
.popChangeHandler(DialogChangeHandler())
)
}
)
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 = [StartPlansDownloadingDialogScreenModule::class],
dependencies = [AppComponent::class])
interface StartPlansDownloadingDialogScreenComponent {
@Component.Factory
interface Factory{
fun create(
appComponent: AppComponent
,@BindsInstance activity: RoomParkMainActivity
): StartPlansDownloadingDialogScreenComponent
}
fun inject(controller: StartPlansDownloadingDialogController)
}
@Module
abstract class StartPlansDownloadingDialogScreenModule{
@PerScreen
@Binds
abstract fun provideActivity(activity: RoomParkMainActivity): BaseRoomParkActivity
}
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.ImageView
import android.widget.ProgressBar
import androidx.annotation.LayoutRes
import androidx.core.os.bundleOf
import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.base.IBottomNavigation
import com.biganto.visual.roompark.base.ICollapsingToolBar
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.ToursInteractor
import com.biganto.visual.roompark.domain.model.TourModel
import com.biganto.visual.roompark.domain.model.fromEntity
import com.biganto.visual.roompark.domain.use_case.DownloadUseCase
import com.biganto.visual.roompark.util.view_utils.snackbar.ISnackBarProvider
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.TourPreviewEntity
import com.bluelinelabs.conductor.Controller
import com.bumptech.glide.Glide
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.
*/
internal const val DOWNLOAD_TOUR_ID_KEY = "DOWNLOAD_TOUR_ID_KEY"
class DownloadTourDialogController : Controller {
constructor(args: Bundle) : super(args)
constructor(tourArg: TourModel) : super(bundleOf(DOWNLOAD_TOUR_ID_KEY to tourArg))
lateinit var progressBarDownload: ProgressBar
lateinit var downloaderBg: ImageView
lateinit var downloadTourTitleText: MaterialTextView
lateinit var cancelDownloadText: MaterialTextView
override fun onContextAvailable(context: Context) {
super.onContextAvailable(context)
DaggerDownloaderScreenComponent.factory()
.create(RoomParkApplication.component,activity as RoomParkMainActivity)
.inject(this)
}
private val tour:TourModel by lazy {
args.getParcelable<TourModel>(DOWNLOAD_TOUR_ID_KEY)
}
private var downloadToken = DownloadUseCase.CancellationToken(false)
@Inject
lateinit var downloader: ToursInteractor
@Inject
lateinit var rpActivity: RoomParkMainActivity
lateinit var snackbar: ISnackBarProvider
private val disposables = CompositeDisposable()
override fun onDetach(view: View) {
disposables.clear()
super.onDetach(view)
}
private val bottomNavigationController: IBottomNavigation by lazy {rpActivity}
private val toolbar: ICollapsingToolBar by lazy {rpActivity}
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)
// progress.visibility = View.VISIBLE
downloadToken = DownloadUseCase.CancellationToken(false)
downloadTourTitleText.text = tour.title
Glide.with(view)
.load(tour.previewUrl)
.transform(BlurTransformation(13, 8)
,ColorFilterTransformation(0x99000000.toInt()))
.into(downloaderBg)
disposables.add(
downloader.downloadTour(tour.tour_id, downloadToken)
.onErrorReturn { Timber.e(it);TourPreviewEntity() }
// .onErrorReturn { parseError(it);TourPreviewEntity() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe (
{ model ->
updateProgressBar(model.downloadedFiles, model.overallFiles)
if (model.overallFiles == model.downloadedFiles)
activity?.let{
startPlayer(it, fromEntity(model))
handleBack()
}
}
,{error ->
Timber.e(error)
snackbar.showSnackBar(error.localizedMessage)
}
))
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 = [DownloaderScreenModule::class],
dependencies = [AppComponent::class])
interface DownloaderScreenComponent {
@Component.Factory
interface Factory{
fun create(
appComponent: AppComponent
,@BindsInstance activity: RoomParkMainActivity
): DownloaderScreenComponent
}
//
// val presenter: ArticlesScreenPresenter
fun inject(controller: DownloadTourDialogController)
}
@Module
abstract class DownloaderScreenModule{
@PerScreen
@Binds
abstract fun provideContext(activity: RoomParkMainActivity): Context
}
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.data.service.network.INetworkMonitor
import com.biganto.visual.roompark.data.service.network.NoNetworkException
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.
*/
class StartToursDownloadingDialogController : Controller {
constructor():super()
constructor(args: Bundle):super(args)
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
@Inject
lateinit var networkMonitor: INetworkMonitor
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)
view.findViewById<MaterialTextView>(R.id.download_dialog_title)
.text = resources?.getString(R.string.download_all_tours_notice_text)
view.findViewById<MaterialTextView>(R.id.all_tours_size_textView)
.text = resources?.getString(R.string.download_all_tours_size_title
,"0")
snackbar = ActivityModule.provideSnackBar(rpActivity)
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(
downloader.fetchToursSizes()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
view.findViewById<MaterialTextView>(R.id.all_tours_size_textView)
.text = resources?.getString(R.string.download_all_tours_size_title
,it.bytesToSize())
}
)
detachDisposable.add(
view.findViewById<Button>(R.id.alert_ok_button)
.clicks()
.filter{
if (!networkMonitor.isConnected){
snackbar.showSnackBar(R.string.no_network_error)
}
networkMonitor.isConnected
}
.debounce(200, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.io())
.flatMap{ downloader.startToursDownloading()}
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({
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
}
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.ImageView
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.conductor.dialogs.change_handler.DialogChangeHandler
import com.biganto.visual.roompark.domain.model.TourModel
import com.biganto.visual.roompark.presentation.screen.settings.util.CommonRecyclerAdapter
import com.biganto.visual.roompark.presentation.screen.settings.util.CommonViewHolder
import com.biganto.visual.roompark.util.extensions.setGone
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.DownloadState
import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.RouterTransaction
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.google.android.material.textview.MaterialTextView
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import java.util.concurrent.TimeUnit
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 09.04.2019.
*/
internal const val TOUR_MODEL_LIST = "CHOOSE_TOUR_LIST_KEY"
private fun formBundle(photos: ArrayList<TourModel>): Bundle {
val b = Bundle()
b.putParcelableArrayList(TOUR_MODEL_LIST,photos)
return b
}
class ChooseTourDialogController : Controller {
constructor(args: Bundle) : super(args)
constructor(items: ArrayList<TourModel>) : super(formBundle(items))
private lateinit var recyclerView : RecyclerView
private val detachDisposable = CompositeDisposable()
override fun onDetach(view: View) {
detachDisposable.clear()
super.onDetach(view)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
val view = inflater.inflate(getLayoutId(), container, false)
recyclerView = view.findViewById(R.id.toursList)
recyclerView.layoutManager =
LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
recyclerView.adapter = TourChooserAdapter()
recyclerView.itemAnimator = null
recyclerView.addItemDecoration(
DividerItemDecoration(activity,DividerItemDecoration.VERTICAL)
)
args.getParcelableArrayList<TourModel>(TOUR_MODEL_LIST)?.let {
(recyclerView.adapter as TourChooserAdapter).setItems(it)
}
detachDisposable.add(
(recyclerView.adapter as TourChooserAdapter)
.onItemClicked
.debounce(300L,TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::onTourClicked)
)
// view.findViewById<View>(R.id.close_current_button).setOnClickListener { handleBack() }
view.setOnClickListener { handleBack() }
return view
}
private fun onTourClicked(tour: TourModel) {
when (tour.downloadState) {
DownloadState.Downloaded -> {
activity?.let { startPlayer(it, tour) }
handleBack()
}
else -> {
router.replaceTopController(
RouterTransaction.with(DownloadTourDialogController(tour))
.popChangeHandler(DialogChangeHandler())
.pushChangeHandler(DialogChangeHandler())
)
}
}
}
@LayoutRes
fun getLayoutId() = R.layout.tours_chooser_screen
override fun handleBack(): Boolean {
return router.popCurrentController()
}
}
internal class TourChooserAdapter:CommonRecyclerAdapter<TourChooserViewHolder,TourModel>(){
override val vhKlazz = TourChooserViewHolder::class
override fun getVhLayout(): Int = R.layout.tour_chooser_viewholder
}
internal class TourChooserViewHolder(itemView: View) :CommonViewHolder<TourModel>(itemView){
@BindView(R.id.tour_preview_imageView)
lateinit var tourPreview : ImageView
@BindView(R.id.tour_name)
lateinit var tourName : MaterialTextView
@BindView(R.id.tour_status_imageView)
lateinit var tourStatus : ImageView
@Inject
lateinit var activity:Context
override fun onViewBound(model: TourModel) {
tourName.text = model.title
Glide.with(tourPreview)
.load(model.previewUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(tourPreview)
tourStatus.setGone(model.downloadState == DownloadState.Downloaded)
tourStatus.setImageDrawable(
itemView.context.resources.getDrawable(
when(model.downloadState){
DownloadState.Downloaded -> R.drawable.ic_download
DownloadState.Suspended -> R.drawable.ic_download
DownloadState.DownloadQueue -> R.drawable.ic_download
else -> R.drawable.ic_download
}
,null)
)
}
}
package com.biganto.visual.roompark.conductor.dialogs.tour_chooser
import android.content.Context
import android.content.Intent
import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.domain.model.TourModel
import com.biganto.visual.roompark.player.BigantoPlayerActivity
import com.biganto.visual.roompark.player.unity_utils.LoadTourConfig
import java.io.File
/**
* Created by Vladislav Bogdashkin on 07.04.2020.
*/
const val PLAY_TOUR_DATA_EXTRAS="BIGANTO_PLAYER_TOUR_DATA"
fun startPlayer(context:Context,tour: TourModel)
{
// hideToursList()
val playerIntent= Intent(context, BigantoPlayerActivity::class.java)
val tourConfig = LoadTourConfig(
tour.tour_id.toInt(),
tour.targetResolution,
FileModule.assetsDirectory(context).plus(File.separator).plus(tour.footageUri),
tour.metaPredict,
tour.previewUrl,
context.resources?.getBoolean(R.bool.isTablet)?.not()?:true,
true
)
playerIntent.putExtra(PLAY_TOUR_DATA_EXTRAS,tourConfig)
context.startActivity(playerIntent)
}
\ No newline at end of file
...@@ -60,7 +60,7 @@ class BigantoMviConductorLifecycleListener<V : MvpView, P : MviPresenter<V, *>> ...@@ -60,7 +60,7 @@ class BigantoMviConductorLifecycleListener<V : MvpView, P : MviPresenter<V, *>>
} }
val viewMpv = callback?.mvpView ?: throw NullPointerException( 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) { if (viewStateWillBeRestored) {
callback!!.setRestoringViewState(true) callback!!.setRestoringViewState(true)
......
package com.biganto.visual.roompark.data
import com.biganto.visual.roompark.base.RoomParkApplication
import com.biganto.visual.roompark.data.service.notification.INotificationCenter
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import timber.log.Timber
import javax.inject.Inject
class RoomParkMessageService : FirebaseMessagingService() {
@Inject
lateinit var notyCenter: INotificationCenter
init {
notyCenter = RoomParkApplication.component.provideNotifivations()
}
override fun onNewToken(p0: String) {
super.onNewToken(p0)
Timber.d("NEW TOKEN REGISTERED: ${p0}")
}
override fun onMessageReceived(remoteMessage: RemoteMessage) { // ...
// TODO(developer): Handle FCM messages here.
// Not getting messages here? See why this may be: https://goo.gl/39bRNJ
Timber.d("From: ${remoteMessage.from}")
// Check if message contains a data payload.
if (remoteMessage.data.size > 0) {
Timber.d("Message data payload: %s", remoteMessage.data)
if ( /* Check if data needs to be processed by long running job */true) { // For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
// scheduleJob()
} else { // Handle message within 10 seconds
// handleNow()
}
}
// Check if message contains a notification payload.
if (remoteMessage.notification != null) {
Timber.d("Message Notification Body: %s", remoteMessage.notification?.body)
notyCenter.showPushNotifyMessage(remoteMessage.notification?.body?:"Уведомление")
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
}
\ No newline at end of file
package com.biganto.visual.roompark.data.data_provider package com.biganto.visual.roompark.data.data_provider
import com.biganto.visual.roompark.data.repository.api.IRoomParkApi 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.ImageAlbumJunctionEntity import com.biganto.visual.roompark.data.repository.db.requrey.model.ImageAlbumJunctionEntity
import com.biganto.visual.roompark.data.repository.mapper.fromRaw import com.biganto.visual.roompark.data.repository.mapper.fromRaw
...@@ -73,7 +73,9 @@ class AlbumsContractModule @Inject constructor( ...@@ -73,7 +73,9 @@ class AlbumsContractModule @Inject constructor(
arrayListOf(fetchTopLevelAlbumsDb,fetchTopLevelAlbumsApi) arrayListOf(fetchTopLevelAlbumsDb,fetchTopLevelAlbumsApi)
) )
.doOnNext { Timber.d("got entity $it") } .doOnNext { Timber.d("got entity $it") }
.map { fromEntity(it,::fromEntity) } .map { fromEntity(it,::fromEntity).sortedByDescending{ album -> album.published } }
//endregion allAlbums //endregion allAlbums
//region concrete Albums //region concrete Albums
......
...@@ -2,11 +2,15 @@ package com.biganto.visual.roompark.data.data_provider ...@@ -2,11 +2,15 @@ package com.biganto.visual.roompark.data.data_provider
import com.biganto.visual.androidplayer.data.repository.local.ILocalStore import com.biganto.visual.androidplayer.data.repository.local.ILocalStore
import com.biganto.visual.roompark.data.local.UserState import com.biganto.visual.roompark.data.local.UserState
import com.biganto.visual.roompark.data.repository.api.IRoomParkApi 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.SubscriptionEntity
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.fromRaw
import com.biganto.visual.roompark.domain.contract.AuthContract import com.biganto.visual.roompark.domain.contract.AuthContract
import com.biganto.visual.roompark.domain.custom_exception.CustomApiException
import com.biganto.visual.roompark.domain.model.AuthInfoModel import com.biganto.visual.roompark.domain.model.AuthInfoModel
import com.biganto.visual.roompark.domain.model.SubscriptionTopic
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
...@@ -35,6 +39,19 @@ class AuthContractModule @Inject constructor( ...@@ -35,6 +39,19 @@ class AuthContractModule @Inject constructor(
api.authenticate(email,password) api.authenticate(email,password)
.map ( ::fromRaw ) .map ( ::fromRaw )
.flatMap{ db.upsertUser(it) } .flatMap{ db.upsertUser(it) }
.flatMap {user ->
val userSubs = user.subscriptions?.map { it as SubscriptionEntity }
var newSubs = defaultSubsList(user)
if (!userSubs.isNullOrEmpty()){
newSubs = newSubs.filter {defSub ->
!userSubs.map { it.topic }.contains(defSub.topic)
}.toList()
}
if (newSubs.isNullOrEmpty()) return@flatMap Observable.just(user)
return@flatMap db.upsert(newSubs)
.toObservable()
.flatMap { db.refreshUser(user) }
}
.doOnNext{ Timber.d("user id: ${it.uuid}")} .doOnNext{ Timber.d("user id: ${it.uuid}")}
.doOnNext { local.setRecentUser(it.uuid.toString()).blockingAwait() } .doOnNext { local.setRecentUser(it.uuid.toString()).blockingAwait() }
.map(::fromEntity) .map(::fromEntity)
...@@ -46,4 +63,53 @@ class AuthContractModule @Inject constructor( ...@@ -46,4 +63,53 @@ class AuthContractModule @Inject constructor(
else ->false else ->false
} } } }
override fun currentUser(): Observable<UserEntity> =
local.recentUser()
.doOnNext { Timber.w("recentUSer: $it") }
.flatMap{ when(it){
is UserState.NotAuthenticated -> throw CustomApiException.NotAuthorizedException()
is UserState.Authenticated -> db.fetchUser(it.uuid.toInt())
.doOnError { Timber.e(it) }
.doOnNext {u-> "got usr:$u" }
else -> throw CustomApiException.NotAuthorizedException()
} }
} }
private fun defaultSubsList(owner:UserEntity) : List<SubscriptionEntity> = arrayListOf(
SubscriptionEntity().apply {
setTopic(SubscriptionTopic.Progress_1().topicName)
setOwner(owner)
setState(false)
}
,SubscriptionEntity().apply {
setTopic(SubscriptionTopic.Progress_2().topicName)
setOwner(owner)
setState(false)
}
,SubscriptionEntity().apply {
setTopic(SubscriptionTopic.Progress_3().topicName)
setOwner(owner)
setState(false)
}
,SubscriptionEntity().apply {
setTopic(SubscriptionTopic.Progress_kindergarden().topicName)
setOwner(owner)
setState(false)
}
,SubscriptionEntity().apply {
setTopic(SubscriptionTopic.News().topicName)
setOwner(owner)
setState(false)
}
,SubscriptionEntity().apply {
setTopic(SubscriptionTopic.Blog().topicName)
setOwner(owner)
setState(false)
}
,SubscriptionEntity().apply {
setTopic(SubscriptionTopic.Construction().topicName)
setOwner(owner)
setState(false)
}
)
\ No newline at end of file
package com.biganto.visual.roompark.data.data_provider
import com.biganto.visual.roompark.domain.contract.DeviceUtilsContract
import com.google.android.gms.tasks.OnCompleteListener
import com.google.firebase.iid.FirebaseInstanceId
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 26.03.2020.
*/
class DeviceUtilsRepository @Inject constructor(
) : DeviceUtilsContract {
override fun getDeviceId(): Observable<String> =
Observable.create<String> {emitter ->
Timber.d("Creat observer")
FirebaseInstanceId.getInstance().instanceId
.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Timber.w(task.exception, "getInstanceId failed")
emitter.onError(task.exception!!)
return@OnCompleteListener
}
// Get new Instance ID token
task.result?.token?.let { emitter.onNext(it) }
emitter.onComplete()
// Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
})
}.subscribeOn(Schedulers.computation())
}
\ No newline at end of file
package com.biganto.visual.roompark.data.data_provider package com.biganto.visual.roompark.data.data_provider
import com.biganto.visual.roompark.data.repository.api.IRoomParkApi 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.ArticleEntity import com.biganto.visual.roompark.data.repository.db.requrey.model.ArticleEntity
import com.biganto.visual.roompark.data.repository.mapper.fromRaw import com.biganto.visual.roompark.data.repository.mapper.fromRaw
......
package com.biganto.visual.roompark.data.data_provider package com.biganto.visual.roompark.data.data_provider
import android.app.Application import android.app.Application
import com.biganto.visual.roompark.data.repository.api.IRoomParkApi 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.file.FileModule import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.domain.contract.FilesContract import com.biganto.visual.roompark.domain.contract.FilesContract
......
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 com.biganto.visual.roompark.domain.use_case.DownloadUseCase
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 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))
).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.absolutePath
}
.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
)
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(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) }.flatMap {
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
package com.biganto.visual.roompark.data.data_provider
import com.biganto.visual.roompark.data.repository.api.room_park.IRoomParkApi
import com.biganto.visual.roompark.data.repository.api.room_park.raw.SubscriptionStatusRaw
import com.biganto.visual.roompark.data.repository.db.IDb
import com.biganto.visual.roompark.data.repository.db.requrey.model.SubscriptionEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.UserEntity
import com.biganto.visual.roompark.domain.contract.SubscriptionContract
import com.biganto.visual.roompark.domain.model.SubscriptionModel
import com.biganto.visual.roompark.domain.model.fromEntity
import io.reactivex.Completable
import io.reactivex.Observable
import timber.log.Timber
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 25.03.2020.
*/
private const val SUBSCRIPTION_RESULT_STATUS = "OK"
class SubscriptionRepository @Inject constructor(
private val api: IRoomParkApi,
private val db: IDb
): SubscriptionContract{
override fun saveSubscribeState(sub:SubscriptionEntity): Observable<SubscriptionEntity> {
return saveSubscribeState(
sub.owner as UserEntity,
sub.id,
sub.topic,
sub.number,
sub.state
)
}
override fun saveSubscribeState(
userEntity: UserEntity,
subInnerId:Int?,
topic: String,
topic_id: String?,
newState:Boolean
): Observable<SubscriptionEntity> {
val userSubs = userEntity.subscriptions
val sub = subInnerId?.let { id ->
userSubs?.firstOrNull { sub -> sub.id == id } as SubscriptionEntity?
}?:SubscriptionEntity()
.apply {
setOwner(userEntity)
setTopic(topic)
setNumber(topic_id)
}
sub.setState(newState)
return db.saveSubscription(sub)
}
fun saveSubscribtions(
userEntity: UserEntity,
apiSubs: List<SubscriptionStatusRaw>
): Observable<List<SubscriptionModel>>? {
val userSubs = userEntity.subscriptions
val newSubList = mutableListOf<SubscriptionEntity>()
apiSubs.forEach { apiSub ->
val cachedSub =
userSubs?.firstOrNull { s ->
s.topic == apiSub.topic && s.number == apiSub.estate_id
}
as SubscriptionEntity?
?: SubscriptionEntity()
.apply {
setOwner(userEntity)
setTopic(apiSub.topic)
setNumber(apiSub.estate_id)
}
cachedSub.setState(apiSub.active)
newSubList.add(cachedSub)
}
userSubs?.filter { !newSubList.map { s ->s.id }.contains(it.id) }?.forEach {
(it as SubscriptionEntity).setState(false)
}
userSubs?.forEach {s ->
if (newSubList.firstOrNull { s.topic == it.topic && s.number == it.number} == null)
newSubList.add(s as SubscriptionEntity)
}
return db.upsert(newSubList)
.map {list -> list.map {
fromEntity(
it as SubscriptionEntity)
}}
.toObservable()
}
override fun subscribeTopicResult(
user:UserEntity,
subInnerId:Int,
deviceToken: String,
topic: String,
topic_id: String?
): Observable<List<SubscriptionModel>> =
api.subscribeTopic(
userToken = user.authToken,
deviceToken = deviceToken
,topicName = topic
,topicId = topic_id)
.flatMap { saveSubscribtions(user,it.subscriptions?: arrayListOf()) }
.doOnNext { db.refreshUser(user).blockingFirst() }
override fun unSubscribeTopicResult(
user:UserEntity,
subInnerId:Int,
deviceToken: String,
topic: String,
topic_id: String?
): Observable<List<SubscriptionModel>> =
api.unSuubscribeTopic(
userToken = user.authToken,
deviceToken = deviceToken
,topicName = topic
,topicId = topic_id)
.flatMap { saveSubscribtions(user,it.subscriptions?: arrayListOf()) }
.doOnNext { db.refreshUser(user) }
override fun subscribeTopic(
user:UserEntity,
subInnerId:Int,
deviceToken: String,
topic: String,
topic_id: String?
): Completable = api.subscribeTopic(
userToken = user.authToken,
deviceToken = deviceToken
,topicName = topic
,topicId = topic_id)
.flatMapCompletable {
if (it.status == SUBSCRIPTION_RESULT_STATUS){
saveSubscribeState(user,subInnerId,topic,topic_id,true)
.ignoreElements()
}
else error("Error subscription state!")
}
override fun unSubscribeTopic(
user:UserEntity,
subInnerId:Int,
deviceToken: String,
topic: String,
topic_id: String?
): Completable =
api.unSuubscribeTopic(
userToken = user.authToken,
deviceToken = deviceToken
,topicName = topic
,topicId = topic_id)
.doOnNext { Timber.d("$it") }
.flatMapCompletable {
if (it.status == SUBSCRIPTION_RESULT_STATUS){
saveSubscribeState(user,subInnerId,topic,topic_id,false)
.ignoreElements()
}
else error("Error subscription state!")
}
}
\ No newline at end of file
package com.biganto.visual.roompark.data.data_provider
import com.biganto.visual.roompark.data.repository.db.IDb
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.domain.contract.TourContract
import com.biganto.visual.roompark.domain.model.AuthInfoModel
import io.reactivex.Completable
import io.reactivex.Observable
import timber.log.Timber
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 29.10.2019.
*/
//@Singleton
class ToursRepository @Inject constructor(
private val files: FileModule,
private val db:IDb
): TourContract {
override fun getMultiTourId(building: Int, number: Int): Observable<AuthInfoModel> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun getOffer(offerId: Int): Observable<AuthInfoModel> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun deleteToursDbInfo(): Completable =
Completable.merge(
arrayListOf(
db.dropTourFileJuncTable(),
db.dropFileTable(),
db.dropTourTable(),
db.refreshEstatesWithTours()
)
)
// .concatWith { }
.doOnComplete { Timber.w("Completed --") }
.doOnError { Timber.e(it) }
}
package com.biganto.visual.roompark.data.memcache
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import com.jakewharton.rxrelay2.Relay
import com.jakewharton.rxrelay2.ReplayRelay
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import timber.log.Timber
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit
/**
* Created by Vladislav Bogdashkin on 19.10.2018.
*/
/**
* @param[maxSize] max entries count before automatic save && flush
* @param[flushInterval] time without any actions with cache in SECONDS before automatic save && flush
* */
abstract class EntityCache<K,V>
constructor(
private val maxSize: Int = 300,
private val flushInterval: Long = TimeUnit.MINUTES.toSeconds(1)
) : Cache<K,V> {
private val disposable = CompositeDisposable()
protected abstract fun saveDelegate (values:List<V>)
protected abstract fun readDelegate (key:K) : V?
protected abstract fun deleteDelegate (value:V)
protected val notifier: Relay<V> = ReplayRelay.create<V>().toSerialized()
init {
disposable.addAll(
Observable.interval(flushInterval, flushInterval, TimeUnit.SECONDS)
.doOnTerminate { clear() }
.doOnDispose { clear() }
.subscribe { clear() }
)
}
override fun contains(key: K): Boolean = keyMap.containsKey(key)
protected val locker = Any()
private var lastFlushTime = System.nanoTime()
private val keyMap = ConcurrentHashMap<K, V>()
override val size: Int
get() = keyMap.size
override val toList
get() = keyMap.toList()
fun deleteEntity(key: K){
synchronized(locker) {
deleteItem(key)
}
}
private fun deleteItem(key:K){
synchronized(locker) {
lastFlushTime = System.nanoTime()
var toDelete = keyMap.remove(key)
if (toDelete == null)
toDelete = readDelegate(key)
if (toDelete == null) return // -> нет в хранилище
deleteDelegate(value = toDelete)
}
}
fun deleteEntitys(keys: List<K>){
synchronized(locker) {
keys.forEach { deleteItem(it)}
}
}
override fun set(key: K, value: V?) {
synchronized(locker) {
lastFlushTime = System.nanoTime()
if (keyMap.size > maxSize)
clear()
value?.let {
keyMap[key]=it
notifier.accept(it)
}
}
}
override fun remove(key: K) = keyMap.remove(key)
override fun get(key: K): V? {
synchronized(locker) {
lastFlushTime = System.nanoTime()
return keyMap[key] ?: readDelegate(key)
}
}
override fun saveAll(){
synchronized(locker)
{
if (keyMap.size > 0) {
Timber.d("Going to save items: ${keyMap.values.size}")
saveDelegate(keyMap.values.toList())
}
}
}
override fun clear() {
if (keyMap.size == 0) return
synchronized(locker)
{
saveAll()
keyMap.clear()
}
}
override fun removeAll(): List<V>? {
val values= keyMap.values.toList()
keyMap.clear()
return values
}
private fun recycle() {
if (keyMap.size<=0) return
val shouldRecycle = System.nanoTime() - lastFlushTime >= TimeUnit.MILLISECONDS.toNanos(flushInterval)
if (!shouldRecycle) return
keyMap.clear()
}
}
interface Cache<K,V> {
val size: Int
val toList:List<Pair<K,V>>
operator fun set(key: K, value: V?)
fun contains(key: K): Boolean
operator fun get(key: K): V?
fun remove(key: K): V?
fun removeAll(): List<V>?
fun clear()
fun saveAll()
}
/**
* Suppress warning Leaking This as we sure to make singletone instance of object in single-thread
* more info and
* @see <a href="https://stackoverflow.com/questions/3921616/leaking-this-in-constructor-warning">discussion</a>
*/
@Suppress("LeakingThis")
abstract class LifeCycleCache<K,V>(size:Int, secondsToFlush:Long)
: EntityCache<K, V>(maxSize=size,flushInterval = secondsToFlush)
, LifecycleObserver
{
init {
ProcessLifecycleOwner.get().lifecycle
.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onAppPaused() {
saveAll()
}
}
package com.biganto.visual.roompark.data.repository.api.biganto
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourFilesDataRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourFilesSimpleDataRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourPreviewRaw
import io.reactivex.*
import io.reactivex.schedulers.Schedulers
import okhttp3.HttpUrl
import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.Retrofit
import timber.log.Timber
import timber.log.Timber.e
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Singleton
/**
* Created by Vladislav Bogdashkin on 13.06.2018.
*/
@Singleton
class BigantoRetrofitRepository @Inject constructor(@Named("bigantoApi") retrofit:Retrofit)
: IBigantoApi{
private val api = retrofit.create(IBigantoMobileApi::class.java)
override fun provideHttpUrl(): HttpUrl {
return HttpUrl.parse(IBigantoMobileApi.BASE_URL)!!
}
override fun getAppVersion() = api
.getAppVersion()
.compose(RetrofitResponseValidation())
override fun getToursPreviewById(tourIds: List<String>): Observable<List<TourPreviewRaw>> {
return api.getToursPreviewById(ids = tourIds.joinToString(","))
.compose(RetrofitResponseValidation())
.subscribeOn(Schedulers.io())
}
override fun getTourMetaAsString(tour_id: String): Observable<String> = api
.getTourMetaAsString(ids = tour_id)
.map { it.toString() }
.doOnError { e(it) }
.subscribeOn(Schedulers.io())
override fun getTourFiles(tour_id: String, resolution: String): Observable<List<TourFilesDataRaw>> = api
.getTourFiles(ids = tour_id, resolution = resolution)
.compose(RetrofitResponseValidation())
.doOnError { e(it) }
.subscribeOn(Schedulers.io())
override fun getTourFilesSizes(ids: List<String>, resolution: String)
: Observable<List<TourFilesSimpleDataRaw>> = api
.getTourFilesSize(ids = ids.joinToString(separator = ","), resolution = resolution)
.compose(RetrofitResponseValidation())
.doOnError { e(it) }
.subscribeOn(Schedulers.io())
override fun downloadFile(uri: String, headers: Map<String, String>?): Flowable<ResponseBody> = api
.requestFile(headers ?: HashMap<String, String>(), uri)
.compose(FlowableRetrofitResponseValidation())
.doOnError(::e)
override fun getOfferTours(multiTourIds:List<Int>): Observable<List<TourPreviewRaw>> =
api
.getOfferTours(offerId = multiTourIds.joinToString(separator = ","))
.compose(RetrofitResponseValidation())
.map { it.values.flatten() }
.doOnError { e(it) }
.subscribeOn(Schedulers.io())
override fun getOfferTours(multiTourId:Int): Observable<List<TourPreviewRaw>> =
api
.getOfferTours(offerId = multiTourId.toString())
.compose(RetrofitResponseValidation())
.map { it[multiTourId.toString()]?.toList()?: error("No tours avaliable")}
.doOnError { e(it) }
.subscribeOn(Schedulers.io())
}
internal class RetrofitResponseValidation<T> : ObservableTransformer<Response<T>, T> {
override fun apply(responseObservable: Observable<Response<T>>): ObservableSource<T> {
return responseObservable.switchMap { resp ->
// Timber.d("reutrned code: %s",resp.code())
if (resp.code() == 200 || resp.code() == 206)
if (resp.body() == null)
return@switchMap Completable.complete().toObservable<T>().doOnNext{Timber.d("Completed responseBody")}
else return@switchMap Observable.just(resp.body())
Timber.d("Returning Exception!")
return@switchMap Observable.error<T>(retrofit2.HttpException(resp))
}
}
}
internal class RetrofitResponseValidationString<String> : ObservableTransformer<Response<String>, String> {
override fun apply(responseObservable: Observable<Response<String>>): ObservableSource<String> {
return responseObservable.switchMap<String> { resp ->
// Timber.d("reutrned code: %s",resp.code())
if (resp.code() == 200)
if (resp.body() == null)
return@switchMap Completable.complete().toObservable<String>().doOnNext{Timber.d("Completed responseBody")}
else return@switchMap Observable.just<String>(resp.body())
Timber.d("Returning Exception!")
return@switchMap Observable.error<String>(retrofit2.HttpException(resp))
}
}
}
internal class FlowableRetrofitResponseValidation<T> : FlowableTransformer<Response<T>, T> {
override fun apply(responseObservable: Flowable<Response<T>>): Flowable<T> {
return responseObservable.switchMap { resp ->
if (resp.code() == 200 || resp.code() == 206)
if (resp.body() == null)
return@switchMap Completable.complete().toFlowable<T>().doOnNext{Timber.d("Completed responseBody")}
else return@switchMap Flowable.just(resp.body())
Timber.d("Returning Exception!")
return@switchMap Flowable.error<T>(retrofit2.HttpException(resp))
}
}
}
//Allow to override HttpException with custom exception output, example:
//sealed class CustomApiException(val code:Int,val biganto_message:String):RuntimeException()
//{
// class RedirectException():CustomApiException(code = 300,biganto_message = "Redirect page..")
// class WrongAuthDataException():CustomApiException(code = 401,biganto_message = "Login or password not allowed")
// class BlockedUserException():CustomApiException(code = 403,biganto_message = "User has been banned")
// class ServerException():CustomApiException(code = 500,biganto_message = "Error server: undefined")
//
//}
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.api.biganto
import com.biganto.visual.roompark.data.repository.api.biganto.raw.AppVersionRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourFilesDataRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourFilesSimpleDataRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourPreviewRaw
import io.reactivex.Flowable
import io.reactivex.Observable
import okhttp3.HttpUrl
import okhttp3.ResponseBody
/**
* Created by Vladislav Bogdashkin on 13.06.2018.
*/
interface IBigantoApi {
fun provideHttpUrl():HttpUrl
fun downloadFile(uri: String, headers: Map<String, String>?): Flowable<ResponseBody>
// fun getToursFiles(tour_ids: List<Int>, resolution: String): Flowable<Map<String, List<TourFileRaw>>>?
fun getTourMetaAsString(tour_id: String): Observable<String>
fun getTourFiles(tour_id: String, resolution: String): Observable<List<TourFilesDataRaw>>
fun getAppVersion(): Observable<AppVersionRaw>
fun getToursPreviewById(tourIds: List<String>): Observable<List<TourPreviewRaw>>
fun getOfferTours(multiTourId:Int): Observable<List<TourPreviewRaw>>
fun getOfferTours(multiTourIds: List<Int>): Observable<List<TourPreviewRaw>>
fun getTourFilesSizes(
ids: List<String>,
resolution: String
): Observable<List<TourFilesSimpleDataRaw>>
}
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.api.biganto
import com.biganto.visual.roompark.data.repository.api.biganto.raw.AppVersionRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourFilesDataRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourFilesSimpleDataRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourPreviewRaw
import com.google.gson.JsonArray
import io.reactivex.Flowable
import io.reactivex.Observable
import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.http.*
import java.util.*
/**
* Created by Vladislav Bogdashkin on 13.06.2018.
*/
interface IBigantoMobileApi {
companion object{
//const val BASE_URL="http://local.biganto.com"
const val BASE_URL="https://biganto.com"
//const val API_URL="api-novus/"
const val API_URL="api/"
const val DELIMITER="?"
const val CLIENT_TYPE_PARAM="client"
const val CLIENT_VERSION_PARAM="client_version"
const val API_VERSION_PARAM="v"
const val AUTH_TOKEN="auth_token"
const val LANG_PARAM="lang"
const val DEFAULT_LANG_VALUE="en"
const val DEFAULT_CLIENT_TYPE="androidplayer"
//const val DEFAULT_CLIENT_TYPE="iosplayer"
const val OLD_CLIENT_TYPE="mobileplayer"
const val DEFAULT_CLIENT_VERSION="3.0"
const val DEFAULT_API_VERSION="2.0"
//region AppInfo
const val GET_APP_VERSION="misc.appVersion"
//endregion
//region Authentication
const val AUTH_METHOD="users/login/"
const val AUTH_METHOD_2_0="users.authorize"
const val AUTH_LOGIN_PARAM="email"
const val AUTH_PASSWORD_PARAM="password"
//endregion
//region GetEstates
const val GET_ESTATES_METHOD="estates.getList"
//endregion
//region Portfolio
const val GET_PORTFOLIO_ESTATES_METHOD="portfolio.getEstates"
const val GET_PORTFOLIO_TOURS_METHOD="portfolio.getTours"
//endregion
//region GetToursPreview
const val GET_TOURS_METHOD="tours.getBadges"//"tours.getList"
//const val PARENT_ESTATE_PARAM="id"
const val PARENT_ESTATE_PARAM="estate_id"
const val TOURS_BY_ID_PARAM="id"
const val TOURS_TYPES_PARAM="types"
const val DEFAULT_SUPPORTED_TOURS_TYPES = "virtual,real"
//endregion
//region GetToursMeta
const val GET_TOURS_META_METHOD="tours.getMeta"
const val GET_TOURS_META_ID="id"
//endregion
//region GetFiles
const val GET_TOURS_FILES_METHOD="tours.getFiles"
const val GET_TOURS_FILES_ID="id"
const val GET_TOURS_FILES_RESOLUTION="resolution"
//endregion
//region offers.GetTours
const val OFFER_GET_TOURS_METHOD="offers.getTours"
const val OFFER_GET_TOURS_ID="id"
//endregion
}
@GET("$API_URL$GET_TOURS_METHOD$DELIMITER")
fun getToursPreviewById(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@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(TOURS_TYPES_PARAM) toursTypes: String = DEFAULT_SUPPORTED_TOURS_TYPES,
@Query(TOURS_BY_ID_PARAM) ids: String
): Observable<Response<List<TourPreviewRaw>>>
@GET("$API_URL$GET_TOURS_META_METHOD$DELIMITER")
fun getTourMetaAsString(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@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(GET_TOURS_META_ID) ids: String
): Observable<JsonArray>
@GET("$API_URL$GET_TOURS_FILES_METHOD$DELIMITER")
fun getTourFiles(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@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(GET_TOURS_FILES_ID) ids: String,
@Query(GET_TOURS_FILES_RESOLUTION) resolution: String
): Observable<Response<List<TourFilesDataRaw>>>
@GET("$API_URL$GET_TOURS_FILES_METHOD$DELIMITER")
fun getTourFilesSize(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@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(GET_TOURS_FILES_ID) ids: String,
@Query(GET_TOURS_FILES_RESOLUTION) resolution: String
): Observable<Response<List<TourFilesSimpleDataRaw>>>
@GET("$API_URL$GET_APP_VERSION$DELIMITER")
fun getAppVersion(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@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
): Observable<Response<AppVersionRaw>>
@GET("$API_URL$OFFER_GET_TOURS_METHOD$DELIMITER")
fun getOfferTours(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@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: String
): Observable<Response<Map<String,List<TourPreviewRaw>>>>
@Streaming
@GET
fun requestFile(
@HeaderMap headers: Map<String, String>?,
@Url fileUrl: String
): Flowable<Response<ResponseBody>>
}
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.api.biganto.raw
import java.util.*
/**
* Created by Vladislav Bogdashkin on 09.06.2018.
*/
data class LiteTourMetaRaw(
val baseurl:String,
val tour_baseurl:String
)
data class ErrorRaw(
val code:Int,
val message:String
)
data class EstatesRaw(
val estates:List<EstateRaw>,
val errors:List<ErrorRaw>?
)
data class EstatesRoomParkRaw(
val estates:Map<String, EstateRoomParkRaw>,
val errors:List<ErrorRaw>?
)
data class EstateRoomParkRaw(
val avaliable:Boolean,
val long: String, //->long name
val short: String //->short name
)
data class TourOverviewsRoomParkRaw(
val tours:List<TourOverviewRoomParkRaw>,
val errors:List<ErrorRaw>?
)
data class TourOverviewRoomParkRaw(
val hidden:Boolean,
val id:String,
val preview: String,
val title: String,
val url:String
)
data class EstateRaw(
val id:Int,
val created:Date,
val title:String,
val preview:String?,
val cnt_tours:Int,
val errors:List<ErrorRaw>?
)
data class ToursPreviewRaw(
val list:List<TourPreviewRaw>,
val errors:List<ErrorRaw>?
)
data class TourPreviewRaw(
val id:Int,
val created:Date,
val updated:Date,
val type:String,
val title:String,
val preview:String,
val screen:String,
val hidden:Boolean,
val resolutions:List<Int>?,
val features:List<String>?,
val errors:List<ErrorRaw>?
)
data class TourFileRaw(
val size:Long,
val url:String,
val errors:List<ErrorRaw>?
)
data class TourFilesSimpleDataRaw(
val id:Int,
val resolution:Int,
val total_size:Long,
val errors:List<ErrorRaw>?
)
data class TourFilesDataRaw(
val files:List<TourFileRaw>,
val id:Int,
val resolution:Int,
val total_size:Long,
val errors:List<ErrorRaw>?
)
data class TourGetFilesRaw(
val data: Map<String,List<TourFileRaw>>,
val errors:List<ErrorRaw>?
)
data class OfferTours(
val data: Map<String,List<TourPreviewRaw>>,
val errors:List<ErrorRaw>?
)
data class AppVersionRaw(
val current_version : String,
val download_url : String?,
val message : String?,
val critical : Boolean,
val errors : List<ErrorRaw>?
)
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.api.retrofit.di package com.biganto.visual.roompark.data.repository.api.retrofit.di
import android.app.Application import android.app.Application
import com.biganto.visual.roompark.data.repository.api.retrofit.IRoomParkMobileApi import com.biganto.visual.roompark.data.repository.api.biganto.IBigantoMobileApi
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.ErrorRaw
import com.biganto.visual.roompark.data.repository.api.retrofit.util.* import com.biganto.visual.roompark.data.repository.api.retrofit.util.*
import com.biganto.visual.roompark.data.repository.api.room_park.IRoomParkMobileApi
import com.biganto.visual.roompark.data.repository.api.room_park.raw.ErrorRaw
import com.biganto.visual.roompark.data.service.network.INetworkMonitor import com.biganto.visual.roompark.data.service.network.INetworkMonitor
import com.biganto.visual.roompark.data.service.network.LiveNetworkMonitor import com.biganto.visual.roompark.data.service.network.LiveNetworkMonitor
import com.biganto.visual.roompark.data.service.network.NoNetworkException import com.biganto.visual.roompark.data.service.network.NoNetworkException
...@@ -22,6 +23,7 @@ import retrofit2.converter.scalars.ScalarsConverterFactory ...@@ -22,6 +23,7 @@ import retrofit2.converter.scalars.ScalarsConverterFactory
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.inject.Named
import javax.inject.Singleton import javax.inject.Singleton
/** /**
...@@ -102,7 +104,7 @@ class RetrofitModule{ ...@@ -102,7 +104,7 @@ class RetrofitModule{
@Provides @Provides
@Singleton @Singleton
// @Named("roomParkApi") @Named("roomParkApi")
fun provideRetrofitRoomParkApi(context: Application): Retrofit = fun provideRetrofitRoomParkApi(context: Application): Retrofit =
Retrofit.Builder() Retrofit.Builder()
.baseUrl(IRoomParkMobileApi.BASE_URL) .baseUrl(IRoomParkMobileApi.BASE_URL)
...@@ -113,4 +115,18 @@ class RetrofitModule{ ...@@ -113,4 +115,18 @@ class RetrofitModule{
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build() .build()
@Provides
@Singleton
@Named("bigantoApi")
fun provideRetrofitBigantoApi(context: Application): Retrofit =
Retrofit.Builder()
.baseUrl(IBigantoMobileApi.BASE_URL)
.client(client(AppVersionManager(context),LiveNetworkMonitor(context)))
.addConverterFactory(NullOnEmptyConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(gsonConverterFactory())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
} }
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.api.retrofit.util package com.biganto.visual.roompark.data.repository.api.retrofit.util
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.ErrorRaw import com.biganto.visual.roompark.data.repository.api.room_park.raw.ErrorRaw
import com.biganto.visual.roompark.domain.custom_exception.parseException import com.biganto.visual.roompark.domain.custom_exception.parseException
import com.google.gson.* import com.google.gson.*
import timber.log.Timber import timber.log.Timber
......
package com.biganto.visual.roompark.data.repository.api.retrofit.util package com.biganto.visual.roompark.data.repository.api.retrofit.util
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.ErrorRaw import com.biganto.visual.roompark.data.repository.api.room_park.raw.ErrorRaw
import com.biganto.visual.roompark.domain.custom_exception.parseException import com.biganto.visual.roompark.domain.custom_exception.parseException
import com.google.gson.JsonDeserializationContext import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer import com.google.gson.JsonDeserializer
......
package com.biganto.visual.roompark.data.repository.api package com.biganto.visual.roompark.data.repository.api.room_park
import com.biganto.visual.roompark.data.repository.api.retrofit.DEFAULT_ARTICLE_PAGE_SIZE import com.biganto.visual.roompark.data.repository.api.room_park.raw.*
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.*
import io.reactivex.Observable import io.reactivex.Observable
/** /**
...@@ -15,13 +14,15 @@ interface IRoomParkApi { ...@@ -15,13 +14,15 @@ interface IRoomParkApi {
fun subscribeTopic( fun subscribeTopic(
userToken: String, userToken: String,
deviceToken: String, deviceToken: String,
topicName: String topicName: String,
topicId:String?
): Observable<StatusResponse> ): Observable<StatusResponse>
fun unSuubscribeTopic( fun unSuubscribeTopic(
userToken: String, userToken: String,
deviceToken: String, deviceToken: String,
topicName: String topicName: String,
topicId:String?
): Observable<StatusResponse> ): Observable<StatusResponse>
fun getDeals(userToken: String): Observable<List<DealRaw>> fun getDeals(userToken: String): Observable<List<DealRaw>>
...@@ -49,6 +50,3 @@ interface IRoomParkApi { ...@@ -49,6 +50,3 @@ interface IRoomParkApi {
fun getWebCamsList(): Observable<List<WebCamRaw>> fun getWebCamsList(): Observable<List<WebCamRaw>>
} }
interface IBigantoApi {
}
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.api.retrofit package com.biganto.visual.roompark.data.repository.api.room_park
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.* import com.biganto.visual.roompark.data.repository.api.room_park.raw.*
import io.reactivex.Observable import io.reactivex.Observable
import retrofit2.Response import retrofit2.Response
import retrofit2.http.* import retrofit2.http.*
...@@ -26,8 +26,8 @@ interface IRoomParkMobileApi{ ...@@ -26,8 +26,8 @@ interface IRoomParkMobileApi{
const val LANG_PARAM="lang" const val LANG_PARAM="lang"
const val DEFAULT_LANG_VALUE="en" const val DEFAULT_LANG_VALUE="en"
const val DEFAULT_CLIENT_TYPE="androidplayer" const val DEFAULT_CLIENT_TYPE="android"
//const val DEFAULT_CLIENT_TYPE="iosplayer" //const val DEFAULT_CLIENT_TYPE="ios"
const val OLD_CLIENT_TYPE="mobileplayer" const val OLD_CLIENT_TYPE="mobileplayer"
const val DEFAULT_CLIENT_VERSION="3.0" const val DEFAULT_CLIENT_VERSION="3.0"
...@@ -48,6 +48,7 @@ interface IRoomParkMobileApi{ ...@@ -48,6 +48,7 @@ interface IRoomParkMobileApi{
const val UNSUBSCRIBE_METHOD="users.unsubscribe" const val UNSUBSCRIBE_METHOD="users.unsubscribe"
const val DEVICE_TOKEN_SUBSCRIBTION_PARAM="deviceToken" const val DEVICE_TOKEN_SUBSCRIBTION_PARAM="deviceToken"
const val TOPIC_SUBSCRIBTION_PARAM="topic" const val TOPIC_SUBSCRIBTION_PARAM="topic"
const val TOPIC_SUBSCRIBTION_TOPIC_ID_PARAM="estate_id"
val topicTypes = arrayOf( val topicTypes = arrayOf(
"deals", "deals",
"progress-1", "progress-1",
...@@ -141,24 +142,28 @@ interface IRoomParkMobileApi{ ...@@ -141,24 +142,28 @@ interface IRoomParkMobileApi{
@Field(PASSWORD_AUTH_PARAM) pwd: String @Field(PASSWORD_AUTH_PARAM) pwd: String
): Observable<Response<AuthRaw>> ): Observable<Response<AuthRaw>>
@POST("$API_URL${SUBSCRIBE_METHOD}OD$DELIMITER") @POST("$API_URL$SUBSCRIBE_METHOD$DELIMITER")
@FormUrlEncoded
fun subscribe( fun subscribe(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE, @Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@Query(CLIENT_VERSION_PARAM) clientVersion: String = DEFAULT_CLIENT_VERSION, @Query(CLIENT_VERSION_PARAM) clientVersion: String = DEFAULT_CLIENT_VERSION,
@Query(API_VERSION_PARAM) apiVersion: String = DEFAULT_API_VERSION, @Query(API_VERSION_PARAM) apiVersion: String = DEFAULT_API_VERSION,
@Query(AUTH_TOKEN) token: String, @Query(AUTH_TOKEN) token: String,
@Query(DEVICE_TOKEN_SUBSCRIBTION_PARAM) deviceToken: String, @Field(DEVICE_TOKEN_SUBSCRIBTION_PARAM) deviceToken: String,
@Query(TOPIC_SUBSCRIBTION_PARAM) topic: String @Field(TOPIC_SUBSCRIBTION_PARAM) topic: String,
@Field(TOPIC_SUBSCRIBTION_TOPIC_ID_PARAM) estateId: String?
): Observable<Response<StatusResponse>> ): Observable<Response<StatusResponse>>
@POST("$API_URL${UNSUBSCRIBE_METHOD}OD$DELIMITER") @POST("$API_URL$UNSUBSCRIBE_METHOD$DELIMITER")
@FormUrlEncoded
fun unsubscribe( fun unsubscribe(
@Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE, @Query(CLIENT_TYPE_PARAM) clientType: String = DEFAULT_CLIENT_TYPE,
@Query(CLIENT_VERSION_PARAM) clientVersion: String = DEFAULT_CLIENT_VERSION, @Query(CLIENT_VERSION_PARAM) clientVersion: String = DEFAULT_CLIENT_VERSION,
@Query(API_VERSION_PARAM) apiVersion: String = DEFAULT_API_VERSION, @Query(API_VERSION_PARAM) apiVersion: String = DEFAULT_API_VERSION,
@Query(AUTH_TOKEN) token: String, @Query(AUTH_TOKEN) token: String,
@Query(DEVICE_TOKEN_SUBSCRIBTION_PARAM) deviceToken: String, @Field(DEVICE_TOKEN_SUBSCRIBTION_PARAM) deviceToken: String,
@Query(TOPIC_SUBSCRIBTION_PARAM) topic: String @Field(TOPIC_SUBSCRIBTION_PARAM) topic: String,
@Field(TOPIC_SUBSCRIBTION_TOPIC_ID_PARAM) estateId: String?
): Observable<Response<StatusResponse>> ): Observable<Response<StatusResponse>>
@GET("$API_URL$DEALS_METHOD$DELIMITER") @GET("$API_URL$DEALS_METHOD$DELIMITER")
......
package com.biganto.visual.roompark.data.repository.api.retrofit package com.biganto.visual.roompark.data.repository.api.room_park
import com.biganto.visual.roompark.data.repository.api.IRoomParkApi import com.biganto.visual.roompark.data.repository.api.room_park.raw.*
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.*
import com.biganto.visual.roompark.util.extensions.asInt import com.biganto.visual.roompark.util.extensions.asInt
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Observable import io.reactivex.Observable
...@@ -12,6 +11,7 @@ import retrofit2.Response ...@@ -12,6 +11,7 @@ import retrofit2.Response
import retrofit2.Retrofit import retrofit2.Retrofit
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named
/** /**
* Created by Vladislav Bogdashkin on 29.10.2019. * Created by Vladislav Bogdashkin on 29.10.2019.
...@@ -19,7 +19,8 @@ import javax.inject.Inject ...@@ -19,7 +19,8 @@ import javax.inject.Inject
const val DEFAULT_ARTICLE_PAGE_SIZE = 10 const val DEFAULT_ARTICLE_PAGE_SIZE = 10
class RetrofitRepository @Inject constructor(retrofit: Retrofit) : IRoomParkApi { class RetrofitRepository @Inject constructor(@Named("roomParkApi") retrofit: Retrofit) :
IRoomParkApi {
private val api = retrofit.create(IRoomParkMobileApi::class.java) private val api = retrofit.create(IRoomParkMobileApi::class.java)
...@@ -35,17 +36,20 @@ class RetrofitRepository @Inject constructor(retrofit: Retrofit) : IRoomParkApi ...@@ -35,17 +36,20 @@ class RetrofitRepository @Inject constructor(retrofit: Retrofit) : IRoomParkApi
override fun subscribeTopic( override fun subscribeTopic(
userToken: String, userToken: String,
deviceToken: String, deviceToken: String,
topicName: String topicName: String,
topicId:String?
): Observable<StatusResponse> = ): Observable<StatusResponse> =
api.subscribe(token = userToken, deviceToken = deviceToken, topic = topicName) api.subscribe(token = userToken, deviceToken = deviceToken, topic = topicName,estateId = topicId)
.doOnError { Timber.w(" WTFF ???") }
.compose(RetrofitResponseValidation()) .compose(RetrofitResponseValidation())
override fun unSuubscribeTopic( override fun unSuubscribeTopic(
userToken: String, userToken: String,
deviceToken: String, deviceToken: String,
topicName: String topicName: String,
topicId:String?
): Observable<StatusResponse> = ): Observable<StatusResponse> =
api.unsubscribe(token = userToken, deviceToken = deviceToken, topic = topicName) api.unsubscribe(token = userToken, deviceToken = deviceToken, topic = topicName,estateId = topicId)
.compose(RetrofitResponseValidation()) .compose(RetrofitResponseValidation())
......
package com.biganto.visual.roompark.data.repository.api.retrofit.raw package com.biganto.visual.roompark.data.repository.api.room_park.raw
import com.google.gson.annotations.Expose
import java.util.* import java.util.*
/** /**
...@@ -13,7 +14,17 @@ data class AuthRaw( ...@@ -13,7 +14,17 @@ data class AuthRaw(
val name:String val name:String
) )
data class StatusResponse(val status:String) data class StatusResponse(
val status:String,
val subscriptions:List<SubscriptionStatusRaw>?
)
data class SubscriptionStatusRaw(
val topic:String,
val estate_id: String,
@Expose
val active: Boolean = true
)
data class DealRaw( data class DealRaw(
val id:String, val id:String,
...@@ -30,6 +41,7 @@ data class EstateRaw( ...@@ -30,6 +41,7 @@ data class EstateRaw(
val id:Int, val id:Int,
val type:String, val type:String,
val number:String, val number:String,
val available:Boolean,
val common_info: CommonInfoRaw, val common_info: CommonInfoRaw,
val plan_png:PlanRaw?, val plan_png:PlanRaw?,
val plan_jpg:PlanRaw?, val plan_jpg:PlanRaw?,
......
package com.biganto.visual.roompark.data.repository.db package com.biganto.visual.roompark.data.repository.db
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString
import com.biganto.visual.roompark.data.repository.db.requrey.model.* import com.biganto.visual.roompark.data.repository.db.requrey.model.*
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.Completable import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
import io.requery.Persistable import io.requery.Persistable
import io.requery.reactivex.ReactiveResult import io.requery.reactivex.ReactiveResult
import io.requery.reactivex.ReactiveScalar
/** /**
* Created by Vladislav Bogdashkin on 29.10.2019. * Created by Vladislav Bogdashkin on 29.10.2019.
*/ */
interface IDb { interface IDb {
fun upsertUser(entity: UserEntity): Observable<UserEntity>? fun upsertUser(entity: UserEntity): Observable<UserEntity>
fun <T : Persistable> upsert(entity: T): Single<T> fun <T : Persistable> upsert(entity: T): Single<T>
fun <T : List<Persistable>> upsert(entity: T): Single<Iterable<Persistable>> fun <T : List<Persistable>> upsert(entity: T): Single<Iterable<Persistable>>
fun fetchFeeds(): Observable<FeedEntity> fun fetchFeeds(): Observable<FeedEntity>
...@@ -27,11 +32,55 @@ interface IDb { ...@@ -27,11 +32,55 @@ interface IDb {
fun getPhotos(albumId: Int): Observable<GalleryPhotoEntity> fun getPhotos(albumId: Int): Observable<GalleryPhotoEntity>
fun getPhoto(photoId: Int): Observable<GalleryPhotoEntity> fun getPhoto(photoId: Int): Observable<GalleryPhotoEntity>
fun getAlbum(albumId: Int): Observable<ImageAlbumEntity> fun getAlbum(albumId: Int): Observable<ImageAlbumEntity>
fun getUserFavorites(uuid: Int): Observable<EstateEntity> fun getUserFavorites(uuid: Int): Observable<EstateEntity?>
fun fetchAllUsers(): Observable<List<UserEntity>> fun fetchAllUsers(): Observable<List<UserEntity>>
fun getEstate(estateId: Int): Observable<EstateEntity> fun getEstate(estateId: Int): Observable<EstateEntity>
fun upsertEstate(entity: EstateEntity) fun upsertEstate(entity: EstateEntity)
fun fetchEstateByNumber(building: Int, number: String): ReactiveResult<EstateEntity> fun fetchEstateByNumber(building: Int, number: String): ReactiveResult<EstateEntity>
fun setArticleReadState(id: Int, state: Boolean): Completable fun setArticleReadState(id: Int, state: Boolean): Completable
fun setDealReadState(id: String, state: Boolean): Completable fun setDealReadState(id: String, state: Boolean): Completable
fun saveSubscription(subscription: SubscriptionEntity): Observable<SubscriptionEntity>
fun getSubscription(id: Int): ReactiveResult<SubscriptionEntity>
fun deleteTourPreview(id: String): Int?
fun deleteTourPreview(entity: TourPreviewEntity)
fun deleteFiles(entity: List<FileEntity>)
fun deleteFile(entity: FileEntity)
fun deleteTourFilesJunction(tourId: String): ReactiveScalar<Int>
fun deleteTourFilesJunction(entity: List<TourFileJunctionEntity>)
fun getTourFilesJunctionUniqueFiles(tourId: String): List<TourFileJunctionEntity?>
fun getTourFilesJunction(tourId: String): ReactiveResult<TourFileJunctionEntity>
fun upsertFileEntity(entity: List<FileEntity>): Observable<Iterable<FileEntity>>
fun upsertFileEntity(entity: FileEntity): Observable<FileEntity>
fun flowableFileEntityes(uris: List<RevisionString>): Flowable<FileEntity>
fun getDownloadedSumFileEntityes(uris: List<RevisionString>): Long
fun fetchTouresWithStates(states: List<DownloadState>): MutableList<TourPreviewEntity>
fun fetchFileEntityes(uris: List<RevisionString>): MutableList<FileEntity>
fun pushFileEntities(uris: List<FileEntity>): Observable<Iterable<FileEntity>>
fun getFileEntity(uri: RevisionString): ReactiveResult<FileEntity>
fun getTourFiles(entity: TourPreviewEntity): MutableList<TourFileJunctionEntity>
fun getTourFiles(tourId: String): MutableList<TourFileJunctionEntity>
fun getTourFilesObservable(tourId: String): ReactiveResult<TourFileJunctionEntity>
fun upsertTourPreview(list: List<TourPreviewEntity>): Observable<Iterable<TourPreviewEntity>>
fun upsertTourPreview(entity: TourPreviewEntity): Observable<TourPreviewEntity>
fun upsertTourFileJunction(entity: List<TourFileJunctionEntity>): Observable<Iterable<TourFileJunctionEntity>>
fun upsertTourFileJunction(entity: TourFileJunctionEntity): Observable<TourFileJunctionEntity>
fun observableTourDownloadState(): Flowable<TourPreviewEntity>
fun getFileEntitysOrDefault(uri: RevisionString): FileEntity
fun getTourPreview(tourId: String): ReactiveResult<TourPreviewEntity>
fun getTourPreviewsObservableResult(estateId: Int): Observable<ReactiveResult<TourPreviewEntity>>
fun getEstateTourPreviews(estateId: Int): Observable<List<TourPreviewEntity>>
fun dropFileTable(): Completable
fun dropTourFileJuncTable(): Completable
fun dropTourTable(): Completable
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>>
fun deleteSubscriptions(entities: List<Subscription>)
fun deleteEstate(entity: List<EstateEntity>)
fun deleteEstate(entity: EstateEntity)
fun getUserDeals(uuid: Int): Observable<DealEntity?>
fun deleteDeal(entity: DealEntity)
fun deleteDeal(entity: List<DealEntity>)
} }
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.db.requrey.model package com.biganto.visual.roompark.data.repository.db.requrey.model
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.TourPreview
import io.requery.* import io.requery.*
/** /**
...@@ -14,6 +15,7 @@ interface Estate : Persistable { ...@@ -14,6 +15,7 @@ interface Estate : Persistable {
val id: Int val id: Int
val type: String val type: String
val number: String val number: String
val available: Boolean
@get:Nullable @get:Nullable
val sectionBegin: Int? val sectionBegin: Int?
@get:Nullable @get:Nullable
...@@ -38,6 +40,11 @@ interface Estate : Persistable { ...@@ -38,6 +40,11 @@ interface Estate : Persistable {
@get:Nullable @get:Nullable
val multitourId: Int? val multitourId: Int?
@get:Nullable
@get:OneToMany(mappedBy = "estate")
val tours: Set<TourPreview>?
@get:Nullable @get:Nullable
val multitourPreview: String? val multitourPreview: String?
...@@ -73,6 +80,6 @@ interface Estate : Persistable { ...@@ -73,6 +80,6 @@ interface Estate : Persistable {
@get:Nullable @get:Nullable
@get:Column(name = "UserContainer") @get:Column(name = "UserContainer")
@get:ForeignKey(references = User::class ) @get:ForeignKey(references = User::class )
@get:OneToOne(mappedBy = "uuid",cascade = [CascadeAction.NONE]) @get:ManyToOne(cascade = [CascadeAction.NONE])
var user:User? var user:User?
} }
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.db.requrey.model
import com.biganto.visual.roompark.data.repository.api.biganto.IBigantoMobileApi.Companion.BASE_URL
import com.biganto.visual.roompark.data.repository.api.biganto.raw.LiteTourMetaRaw
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourFileRaw
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString
import com.biganto.visual.roompark.data.repository.db.requrey.utils.RevisionStringConverter
import com.biganto.visual.roompark.data.repository.file.FileModule
import io.requery.*
import java.io.File
import java.math.BigInteger
import java.security.MessageDigest
/**
* Created by Vladislav Bogdashkin on 15.06.2018.
*/
val domainPredicthMatcher = "^(http|https)://".toRegex()
fun toInitialName(fullPath: String) = String.format(
"%032x"
, BigInteger(
1
, MessageDigest.getInstance("MD5").digest(fullPath.toByteArray(Charsets.UTF_8))
)
)
@Entity
interface File :Persistable {
// @get:Key
// var id: String
// @get:Convert(URIConverter::class)
@get:Key
@get:Convert(RevisionStringConverter::class)
val uri: RevisionString
val totalSize: Long
val downloadedSize: Long
@get:Nullable
val isDownloaded: Boolean
@get:Nullable
val destination: String
}
fun fromRaw(raw: TourFileRaw, meta: LiteTourMetaRaw):FileEntity {
val entity = FileEntity()
entity.setDownloaded(false)
entity.setDownloadedSize(0L)
entity.setTotalSize(raw.size)
var fileUri=raw.url
domainPredicthMatcher.containsMatchIn(raw.url)
val bui = raw.url.indexOf(meta.baseurl)
if (bui>=0) fileUri = toInitialName(meta.baseurl)
.plus(File.separator)
.plus(raw.url.removeRange(0,bui+meta.baseurl.length))
val tui = raw.url.indexOf(meta.tour_baseurl)
if (tui>=0) fileUri = toInitialName(meta.tour_baseurl)
.plus(File.separator)
.plus(raw.url.removeRange(0,tui+meta.tour_baseurl.length))
entity.setUri(RevisionString(FileModule.assetsLocalPath(fileUri)))
entity.setDestination(
if (domainPredicthMatcher.containsMatchIn(raw.url)) raw.url
else BASE_URL.plus(raw.url)
)
return entity
}
fun fromRaw(raw: List<TourFileRaw>, meta: LiteTourMetaRaw): List<FileEntity> =
List(raw.size) { index-> fromRaw(raw[index],meta) }
...@@ -15,8 +15,9 @@ interface Subscription : Persistable { ...@@ -15,8 +15,9 @@ interface Subscription : Persistable {
@get:ForeignKey(references = User::class, referencedColumn = "uuid") @get:ForeignKey(references = User::class, referencedColumn = "uuid")
@get:ManyToOne @get:ManyToOne
val owner: User val owner: User
val deviceToken: String
val topic: String val topic: String
val number: String
@get:Nullable
val number: String? //estateId or smth same, depends on subscription case
val state: Boolean val state: Boolean
} }
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.db.requrey.model
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString
import com.biganto.visual.roompark.data.repository.db.requrey.utils.RevisionStringConverter
import io.requery.*
/**
* Created by Vladislav Bogdashkin on 15.06.2018.
*/
@Entity
interface TourFileJunction :Persistable {
@get:Key
@get:Generated
val id: Int
// @get:OneToOne( cascade = [CascadeAction.NONE])
// val tour: TourPreview
//+@get:ForeignKey(delete = ReferentialAction.NO_ACTION, update = ReferentialAction.NO_ACTION, references = TourPreviewEntity::class)
val tour: String
// @get:OneToOne( cascade = [CascadeAction.NONE])
// val file: File
//@get:ForeignKey(delete = ReferentialAction.NO_ACTION, update = ReferentialAction.NO_ACTION, references = FileEntity::class)
@get:Convert(RevisionStringConverter::class)
val file: RevisionString
}
package com.biganto.visual.roomparkvr.data.repository.db.requery.model
import com.biganto.visual.roompark.data.repository.api.biganto.raw.TourPreviewRaw
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString
import com.biganto.visual.roompark.data.repository.db.requrey.model.Estate
import com.biganto.visual.roompark.data.repository.db.requrey.model.EstateEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.domainPredicthMatcher
import com.biganto.visual.roompark.data.repository.db.requrey.utils.IntListConverter
import com.biganto.visual.roompark.data.repository.db.requrey.utils.IsoDateConverter
import com.biganto.visual.roompark.data.repository.db.requrey.utils.RevisionStringConverter
import io.requery.*
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.abs
/**
* Created by Vladislav Bogdashkin on 15.06.2018.
*/
@Entity
interface TourPreview :Persistable {
@get:Key
val id: String
@get:ForeignKey(references = Estate::class)
@get:ManyToOne
var estate: Estate
//Obsolete
// @get:ForeignKey(references = Tour::class)
// @get:OneToOne(mappedBy = "id", cascade = arrayOf(CascadeAction.SAVE))
// var tour: Tour?
@get:Convert(IsoDateConverter::class)
val created: Date
@get:Convert(IsoDateConverter::class)
val updated: Date
val type: String
val screen: String
val title: String
val preview: String?
val hidden: Boolean
var isDownloaded: DownloadState
var overallSize:Long
var tempSize:Long
var downloadedSize:Long
var overallFiles:Int
var downloadedFiles:Int
var targetResolution : Int
@get:Convert(IntListConverter::class)
var resolutions:ArrayList<Int>
// @get:JunctionTable(name= "TourFilesRule")
// @get:ManyToMany( cascade = arrayOf(CascadeAction.NONE))
// @get:Convert(RevisionStringListConverter::class)
// var tourFiles: ArrayList<RevisionString>?
//
@get:Convert(RevisionStringConverter::class)
val metaFileEntityId: RevisionString?
val tourBaseUrl: String?
val footageBaseUrl: String?
}
fun fromRaw(raw: TourPreviewRaw, parentId:Int, baseUrl:String, userResolution:Int):TourPreviewEntity{
val tour=TourPreviewEntity()
tour.setId(raw.id.toString())
tour.setCreated(raw.created)
tour.setUpdated(raw.updated)
tour.setType(raw.type)
tour.setTitle(raw.title)
tour.setPreview(
if (domainPredicthMatcher.containsMatchIn(raw.preview)) raw.preview
else "$baseUrl${raw.preview}"
)
tour.setScreen(
if (domainPredicthMatcher.containsMatchIn(raw.screen)) raw.screen
else "$baseUrl${raw.screen}"
)
tour.setHidden(raw.hidden)
tour.resolutions= if (raw.resolutions != null && !raw.resolutions.isNullOrEmpty()) ArrayList(raw.resolutions)
else ArrayList(1024)
tour.targetResolution=raw.resolutions?.nearestResolution(userResolution)?:1024
val estate= EstateEntity()
estate.setId(parentId)
tour.estate=estate
tour.isDownloaded=DownloadState.NotDownloaded
tour.overallSize=0L
tour.downloadedSize=0L
tour.tempSize=0L
tour.overallFiles=0
tour.downloadedFiles=0
// val tourMeta= TourEntity()
// tourMeta.setId(raw.id.toString())
// tour.tour=tourMeta
return tour
}
fun List<Int>.nearestResolution(targetResolution:Int ):Int{
var lastScore=Int.MAX_VALUE
var lastRes=0
for (res in this){
var d = targetResolution-res
if (d>0) d*=2
d=abs(d)
if (d<lastScore){lastScore=d;lastRes=res}
}
// Timber.d("Resolutions: $this / t=$targetResolution final=$lastRes score=$lastScore")
return lastRes
}
fun fromRaw(raw: List<TourPreviewRaw>, parentId:Int, url:String, userResolution:Int):List<TourPreviewEntity> =List(raw.size) { index-> fromRaw(raw[index],parentId,url,userResolution) }
enum class DownloadState(val i:Int):Comparable<DownloadState>{
NotDownloaded(0),
MetaPreparation(1),
DownloadQueue(2),
Downloading(3),
Suspended(4),
Downloaded(5),
Crushed(6),
Deleting(7),
NotSynced(20);
}
...@@ -24,5 +24,14 @@ interface User : Persistable { ...@@ -24,5 +24,14 @@ interface User : Persistable {
@get:Nullable @get:Nullable
@get:OneToMany(cascade = [CascadeAction.DELETE]) @get:OneToMany(cascade = [CascadeAction.DELETE])
val deals:List<Deal>? val deals:List<Deal>?
@get:Nullable
@get:OneToMany(cascade = [CascadeAction.DELETE])
val estates:List<Estate>?
@get:Nullable
@get:OneToMany(cascade = [CascadeAction.DELETE])
val subscriptions:List<Subscription>?
} }
package com.biganto.visual.roompark.data.repository.db.requrey.utils;
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString;
import io.requery.Converter;
/**
* Created by Vladislav Bogdashkin on 04.07.2018.
*/
public class RevisionStringConverter implements Converter<RevisionString, String> {
@SuppressWarnings("unchecked")
@Override
public Class<RevisionString> getMappedType() {
return RevisionString.class;
}
@Override
public Class<String> getPersistedType() {
return String.class;
}
@Override
public Integer getPersistedSize() {
return null;
}
@Override
public String convertToPersisted(RevisionString value) {
return value == null ? null : value.revisionUri();
}
@Override
public RevisionString convertToMapped(Class<? extends RevisionString> type,
String value) {
return value == null ? null : new RevisionString(value);
}
}
\ No newline at end of file
package com.biganto.visual.roompark.data.repository.db.requrey.utils;
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString;
import java.util.ArrayList;
import io.requery.Converter;
public class RevisionStringListConverter implements Converter<ArrayList<RevisionString>, String> {
private static final String stringDelimeter=">RS<";
@SuppressWarnings("unchecked")
@Override
public Class<ArrayList<RevisionString>> getMappedType() {
return (Class)ArrayList.class;
}
@Override
public Class<String> getPersistedType() {
return String.class;
}
@Override
public Integer getPersistedSize() {
return null;
}
@Override
public String convertToPersisted(ArrayList<RevisionString> value) {
if (value == null) {
return "";
}
StringBuilder sb = new StringBuilder();
int index = 0;
for (RevisionString str: value) {
if (index > 0) {
sb.append(stringDelimeter);
}
sb.append(str.revisionUri());
index++;
}
return sb.toString();
}
@Override
public ArrayList<RevisionString> convertToMapped(Class<? extends ArrayList<RevisionString>> type,
String value) {
ArrayList<RevisionString> list = new ArrayList<>();
if (value != null && !value.isEmpty())
for (String s : value.split(stringDelimeter))
list.add(new RevisionString(s));
return list;
}
}
...@@ -8,6 +8,7 @@ import com.google.gson.JsonElement ...@@ -8,6 +8,7 @@ import com.google.gson.JsonElement
import dagger.Module import dagger.Module
import io.reactivex.Observable import io.reactivex.Observable
import kotlinx.io.IOException import kotlinx.io.IOException
import okio.Okio
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
...@@ -33,8 +34,13 @@ class FileModule @Inject constructor(val context: Application) { ...@@ -33,8 +34,13 @@ class FileModule @Inject constructor(val context: Application) {
fun getFile(fileUri: String): File { fun getFile(fileUri: String): File {
try { try {
val fileName =if (fileUri.contains("/")) fileUri.substring(fileUri.lastIndexOf("/")) else fileUri val fileName =
val fileDir = if (fileUri.contains("/")) fileUri.substring(0, fileUri.lastIndexOf("/")) else "" if (fileUri.contains("/")) fileUri.substring(fileUri.lastIndexOf("/"))
else fileUri
val fileDir =
if (fileUri.contains("/"))
fileUri.substring(0, fileUri.lastIndexOf("/"))
else ""
val directory = File(rootFolder, fileDir) val directory = File(rootFolder, fileDir)
directory.mkdirs() directory.mkdirs()
...@@ -53,15 +59,45 @@ class FileModule @Inject constructor(val context: Application) { ...@@ -53,15 +59,45 @@ class FileModule @Inject constructor(val context: Application) {
file.writeText("[$jsonElement]") //to json array because core unity method parse data like TourData[] Estate[] etc.. 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){ 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..
} }
fun deleteFile(uri:String)= getFile(uri).delete() // fun deleteFile(uri:String)= getFile(uri).delete()
fun deleteAssetFile(uri:String) =
getAssetFile(uri).delete()
fun getAssetFile(uri:String) =
File(assetsDirectory(context).plus(uri))
fun deleteAllCacheObservable() = fun deleteAllCacheObservable() =
Observable.create<Pair<Int, Int>> {emitter -> Observable.create<Pair<Int, Int>> {emitter ->
...@@ -80,18 +116,26 @@ class FileModule @Inject constructor(val context: Application) { ...@@ -80,18 +116,26 @@ class FileModule @Inject constructor(val context: Application) {
} }
val getCoreCacheDirectory:String val getCoreCacheDirectory:String
get(){ get(){
return rootFolder.absolutePath return rootFolder.absolutePath
} }
val freeSpace = rootFolder.freeSpace
companion object { companion object {
fun getDirectory(context: Context, dirType: FileDirectory): File = fun getDirectory(context: Context, dirType: FileDirectory): File =
File(context.filesDir.absolutePath.plus(dirType.dir)) File(context.filesDir.absolutePath.plus(dirType.dir))
fun assetsDirectory(context: Context): String = context.filesDir.absolutePath fun assetsDirectory(context: Context): String =
getDirectory(context,FileDirectory.ToursDir(BIGANTO_TOURS_FOLDER)).absolutePath
fun assetsFile(context: Context): File =
getDirectory(context,FileDirectory.ToursDir(BIGANTO_TOURS_FOLDER))
fun assetsLocalPath(uri:String): String =
FileDirectory.ToursDir(BIGANTO_TOURS_FOLDER).dir.plus(File.separator).plus(uri)
fun assetsFile(context: Context): File = context.filesDir.absoluteFile private const val BIGANTO_TOURS_FOLDER = "biganto"
} }
......
package com.biganto.visual.roompark.data.repository.mapper package com.biganto.visual.roompark.data.repository.mapper
import android.content.res.Resources import android.content.res.Resources
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.* import com.biganto.visual.roompark.data.repository.api.room_park.raw.*
import com.biganto.visual.roompark.data.repository.db.requrey.PhotoResolutions import com.biganto.visual.roompark.data.repository.db.requrey.PhotoResolutions
import com.biganto.visual.roompark.data.repository.db.requrey.TitledPhoto import com.biganto.visual.roompark.data.repository.db.requrey.TitledPhoto
import com.biganto.visual.roompark.data.repository.db.requrey.model.* import com.biganto.visual.roompark.data.repository.db.requrey.model.*
...@@ -113,11 +113,11 @@ fun fromRaw(raw:DealRaw):DealEntity { ...@@ -113,11 +113,11 @@ fun fromRaw(raw:DealRaw):DealEntity {
} }
fun fromRaw(raw:DealRaw,user:UserEntity):DealEntity { fun fromRaw(raw:DealRaw,user:UserEntity):DealEntity =
val entity = fromRaw(raw) fromRaw(raw).apply {
entity.user = user this.user = user
return entity this.estate.user = user
} }
...@@ -126,6 +126,7 @@ fun fromRaw(raw:EstateRaw):EstateEntity{ ...@@ -126,6 +126,7 @@ fun fromRaw(raw:EstateRaw):EstateEntity{
entity.setId(raw.id) entity.setId(raw.id)
entity.setType(raw.type) entity.setType(raw.type)
entity.setNumber(raw.number) entity.setNumber(raw.number)
entity.setAvailable(raw.available)
entity.setSectionBegin(raw.common_info.section_begin) entity.setSectionBegin(raw.common_info.section_begin)
entity.setSectionEnd(raw.common_info.section_end) entity.setSectionEnd(raw.common_info.section_end)
entity.setPlanJpgUrl(raw.plan_jpg?.url) entity.setPlanJpgUrl(raw.plan_jpg?.url)
......
package com.biganto.visual.roompark.data.service.download
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString
import com.biganto.visual.roompark.data.repository.db.requrey.model.FileEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.TourFileJunctionEntity
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.DownloadState
/**
* Created by Vladislav Bogdashkin on 14.04.2020.
*/
data class TourFileData(
val fileUrl: RevisionString,
val tourId: String,
var tempDownloadedSize: Long = 0L,
var tempOverallFileSize: Long = 0L,
var fileDownloadedSize: Long = 0L,
var tempTourTotalDiff: Long = 0L,
var isDownloaded: Boolean = false,
val fatalState: DownloadState? = null,
var destination: String
) {
constructor(entity: FileEntity, junction: TourFileJunctionEntity) : this(
fileUrl = junction.file
, tourId = junction.tour
, tempDownloadedSize = 0L
, tempOverallFileSize = entity.totalSize
, fileDownloadedSize = entity.downloadedSize
, tempTourTotalDiff = 0L
, isDownloaded = entity.isDownloaded
, destination = entity.destination
)
}
package com.biganto.visual.roompark.data.service.lifecycle
/**
* Created by Vladislav Bogdashkin on 14.04.2020.
*/
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AppLifecycleListener @Inject constructor(): ForegroundLifecycleObserver {
private var isForeground=false
override val isAppForeground : Boolean
get() = isForeground
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
Timber.d("Returning to foreground…")
isForeground=true
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onMoveToBackground() {
Timber.d("Moving to background…")
isForeground=false
}
}
interface ForegroundLifecycleObserver : LifecycleObserver{
val isAppForeground : Boolean
}
\ No newline at end of file
package com.biganto.visual.roompark.data.service.network package com.biganto.visual.roompark.data.service.network
import android.app.Application
import android.content.Context import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
...@@ -9,7 +11,7 @@ import javax.inject.Singleton ...@@ -9,7 +11,7 @@ import javax.inject.Singleton
* Created by Vladislav Bogdashkin on 12.10.2018. * Created by Vladislav Bogdashkin on 12.10.2018.
*/ */
@Singleton @Singleton
class LiveNetworkMonitor(val context: Context) : INetworkMonitor { class LiveNetworkMonitor @Inject constructor(val context: Application) : INetworkMonitor {
override val isConnected: Boolean override val isConnected: Boolean
...@@ -23,7 +25,8 @@ class LiveNetworkMonitor(val context: Context) : INetworkMonitor { ...@@ -23,7 +25,8 @@ class LiveNetworkMonitor(val context: Context) : INetworkMonitor {
override val isWifiConnected: Boolean override val isWifiConnected: Boolean
get() { get() {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return cm.activeNetworkInfo != null && (cm.activeNetworkInfo.type == ConnectivityManager.TYPE_WIFI); return cm.activeNetworkInfo != null
&& (cm.activeNetworkInfo.type == ConnectivityManager.TYPE_WIFI);
} }
} }
......
...@@ -4,7 +4,7 @@ import android.content.Context ...@@ -4,7 +4,7 @@ import android.content.Context
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import com.biganto.visual.roompark.BuildConfig import com.biganto.visual.roompark.BuildConfig
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.AppVersionRaw import com.biganto.visual.roompark.data.repository.api.room_park.raw.AppVersionRaw
import com.jakewharton.rxrelay2.BehaviorRelay import com.jakewharton.rxrelay2.BehaviorRelay
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
......
...@@ -4,11 +4,15 @@ import android.app.Application ...@@ -4,11 +4,15 @@ import android.app.Application
import com.biganto.visual.androidplayer.data.repository.local.ILocalStore import com.biganto.visual.androidplayer.data.repository.local.ILocalStore
import com.biganto.visual.roompark.base.RoomParkApplication import com.biganto.visual.roompark.base.RoomParkApplication
import com.biganto.visual.roompark.data.local.LocalStorage import com.biganto.visual.roompark.data.local.LocalStorage
import com.biganto.visual.roompark.data.repository.api.IRoomParkApi import com.biganto.visual.roompark.data.repository.api.biganto.IBigantoApi
import com.biganto.visual.roompark.data.repository.api.retrofit.di.RetrofitModule import com.biganto.visual.roompark.data.repository.api.retrofit.di.RetrofitModule
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.DbModule import com.biganto.visual.roompark.data.repository.db.requrey.DbModule
import com.biganto.visual.roompark.data.repository.file.FileModule 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.network.INetworkMonitor
import com.biganto.visual.roompark.data.service.notification.INotificationCenter
import com.biganto.visual.roompark.domain.contract.* import com.biganto.visual.roompark.domain.contract.*
import dagger.BindsInstance import dagger.BindsInstance
import dagger.Component import dagger.Component
...@@ -17,10 +21,6 @@ import dagger.android.AndroidInjector ...@@ -17,10 +21,6 @@ import dagger.android.AndroidInjector
import dagger.android.support.AndroidSupportInjectionModule import dagger.android.support.AndroidSupportInjectionModule
import javax.inject.Singleton import javax.inject.Singleton
/** /**
* Created by Vladislav Bogdashkin on 13.06.2018. * Created by Vladislav Bogdashkin on 13.06.2018.
*/ */
...@@ -53,13 +53,29 @@ interface AppComponent : AndroidInjector<RoomParkApplication>{ ...@@ -53,13 +53,29 @@ interface AppComponent : AndroidInjector<RoomParkApplication>{
fun filesRep(): FilesContract fun filesRep(): FilesContract
fun subsRep(): SubscriptionContract
fun provideLocal():ILocalStore fun provideLocal():ILocalStore
fun provideApi():IRoomParkApi fun provideApi(): IRoomParkApi
fun provideBigantoApi(): IBigantoApi
fun providedb():IDb fun providedb():IDb
fun provideUtils():DeviceUtilsContract
fun provideTour():TourContract
fun providePlan():FlatPlanContract
fun provideLifeCycle(): ForegroundLifecycleObserver
fun provideNotifivations(): INotificationCenter
fun provideNetMonitor(): INetworkMonitor
fun provideAppContext():Application fun provideAppContext():Application
fun provideFileSystem(): FileModule fun provideFileSystem(): FileModule
...@@ -72,41 +88,5 @@ interface AppComponent : AndroidInjector<RoomParkApplication>{ ...@@ -72,41 +88,5 @@ interface AppComponent : AndroidInjector<RoomParkApplication>{
@BindsInstance app:RoomParkApplication @BindsInstance app:RoomParkApplication
):AppComponent ):AppComponent
// @BindsInstance
// fun context(application: Application): Factory
// @BindsInstance
// fun retrofitModule(retrofit: RetrofitModule):Builder
// @BindsInstance
// @Named("roomParkApi")
// fun retrofit(
// retorfitModule: RetrofitModule
// ): DaggerDataComponent.Builder
//
// fun build(): AppComponent
} }
// retorfitModule: RetrofitModule
// fun cache(): ICachedStore
// fun context(): Context
// fun db(): IDb
// fun api(): IApi
// fun roomApi(): IRoomParkApi
// fun fileModule(): FilesModule
//// fun appLifeCycle(): AppLifecycleListener
// fun networkMonitor(): INetworkMonitor
// fun versionMonitor(): IAppVersionControl
// fun versionNotifier(): IAppVersionNotifier
//
// fun estateRepo() : IEstateRepository
// fun tourRepo() : ITourRepository
// fun userRepo() : IUserRepository
} }
\ No newline at end of file
...@@ -9,19 +9,6 @@ import dagger.Module ...@@ -9,19 +9,6 @@ import dagger.Module
* Created by Vladislav Bogdashkin on 13.06.2018. * Created by Vladislav Bogdashkin on 13.06.2018.
*/ */
const val USER_CACHE_LIMIT_SIZE = 3
const val USER_CACHE_LIMIT_SECONDS_INACTIVE = 30L
const val TOURS_CACHE_LIMIT_SIZE = 500
const val TOURS_CACHE_LIMIT_SECONDS_INACTIVE = 200L
const val ESTATES_CACHE_LIMIT_SIZE = 100
const val ESTATES_CACHE_LIMIT_SECONDS_INACTIVE = 200L
const val FILES_CACHE_LIMIT_SIZE = 10000
const val FILES_CACHE_LIMIT_SECONDS_INACTIVE = 60L
const val DATABASE_VERSION = 11
@Module @Module
abstract class AppModule{ abstract class AppModule{
......
package com.biganto.visual.roompark.domain.contract package com.biganto.visual.roompark.domain.contract
import com.biganto.visual.roompark.data.repository.db.requrey.model.UserEntity
import com.biganto.visual.roompark.domain.model.AuthInfoModel import com.biganto.visual.roompark.domain.model.AuthInfoModel
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Observable import io.reactivex.Observable
...@@ -12,4 +13,5 @@ interface AuthContract { ...@@ -12,4 +13,5 @@ interface AuthContract {
fun signIn(email:String,password:String) : Observable<AuthInfoModel> fun signIn(email:String,password:String) : Observable<AuthInfoModel>
fun signOut() : Completable fun signOut() : Completable
fun validateAuthState(): Observable<Boolean> fun validateAuthState(): Observable<Boolean>
fun currentUser(): Observable<UserEntity>
} }
\ No newline at end of file
package com.biganto.visual.roompark.domain.contract package com.biganto.visual.roompark.domain.contract
import com.biganto.visual.roompark.domain.model.DealModel 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.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
...@@ -13,20 +14,11 @@ import io.reactivex.Observable ...@@ -13,20 +14,11 @@ import io.reactivex.Observable
interface DealContract{ 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 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
fun fetchDeals(user: UserEntity): Observable<List<DealEntity>>
fun fetchFavorites(user: UserEntity): Observable<List<EstateEntity>>
fun getDealsApi(user: UserEntity): Observable<List<DealEntity>>
} }
\ No newline at end of file
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
/**
* 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>
fun getPlansObservable(
list: List<PlanFeaturesVariant>,
cancellationToken: DownloadUseCase.CancellationToken
): Observable<String>
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ package com.biganto.visual.roompark.domain.custom_exception ...@@ -2,7 +2,7 @@ package com.biganto.visual.roompark.domain.custom_exception
import androidx.annotation.StringRes import androidx.annotation.StringRes
import com.biganto.visual.roompark.R import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.data.repository.api.retrofit.raw.ErrorRaw import com.biganto.visual.roompark.data.repository.api.room_park.raw.ErrorRaw
/** /**
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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