Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Room Park Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vladislav Bogdashkin
Room Park Android
Commits
5d7e5a33
Commit
5d7e5a33
authored
Nov 18, 2019
by
Vladislav Bogdashkin
🎣
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/login' into develop
parents
9678c356
f5ee4da1
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
271 additions
and
100 deletions
+271
-100
BigantoBaseController.kt
...iganto/visual/roompark/conductor/BigantoBaseController.kt
+8
-0
BigantoBasePresenter.kt
...biganto/visual/roompark/conductor/BigantoBasePresenter.kt
+18
-9
UserHolder.kt
...java/com/biganto/visual/roompark/data/local/UserHolder.kt
+9
-2
IRoomParkMobileApi.kt
...ompark/data/repository/api/retrofit/IRoomParkMobileApi.kt
+4
-5
CustomExceptionDeserializer.kt
...pository/api/retrofit/util/CustomExceptionDeserializer.kt
+5
-10
ContextModule.kt
...va/com/biganto/visual/roompark/di/dagger/ContextModule.kt
+3
-1
settings.kt
...com/biganto/visual/roompark/domain/interactor/settings.kt
+5
-0
authUseCase.kt
...om/biganto/visual/roompark/domain/use_case/authUseCase.kt
+1
-3
ScreenController.kt
...ual/roompark/presentation/screen/auth/ScreenController.kt
+69
-11
ScreenDI.kt
...anto/visual/roompark/presentation/screen/auth/ScreenDI.kt
+5
-0
ScreenPresenter.kt
...sual/roompark/presentation/screen/auth/ScreenPresenter.kt
+21
-5
ScreenViewState.kt
...sual/roompark/presentation/screen/auth/ScreenViewState.kt
+3
-0
HomeBottomNavigationController.kt
...creen/home/home_routing/HomeBottomNavigationController.kt
+17
-22
ScreenContract.kt
...l/roompark/presentation/screen/settings/ScreenContract.kt
+2
-0
ScreenController.kt
...roompark/presentation/screen/settings/ScreenController.kt
+22
-0
ScreenDI.kt
.../visual/roompark/presentation/screen/settings/ScreenDI.kt
+11
-4
ScreenPresenter.kt
.../roompark/presentation/screen/settings/ScreenPresenter.kt
+11
-0
ScreenViewState.kt
.../roompark/presentation/screen/settings/ScreenViewState.kt
+1
-0
ScreenController.kt
...l/roompark/presentation/screen/splash/ScreenController.kt
+7
-2
ScreenDI.kt
...to/visual/roompark/presentation/screen/splash/ScreenDI.kt
+5
-0
ScreenPresenter.kt
...al/roompark/presentation/screen/splash/ScreenPresenter.kt
+6
-0
either.kt
...n/java/com/biganto/visual/roompark/util/monades/either.kt
+10
-7
sign_in_button_selector.xml
app/src/main/res/color/sign_in_button_selector.xml
+3
-2
activity_main.xml
app/src/main/res/layout/activity_main.xml
+9
-10
authentication_screen.xml
app/src/main/res/layout/authentication_screen.xml
+9
-2
settings_screen.xml
app/src/main/res/layout/settings_screen.xml
+5
-5
styles.xml
app/src/main/res/values/styles.xml
+2
-0
No files found.
app/src/main/java/com/biganto/visual/roompark/conductor/BigantoBaseController.kt
View file @
5d7e5a33
...
@@ -19,6 +19,7 @@ import com.biganto.visual.roompark.util.monades.ExceptionString
...
@@ -19,6 +19,7 @@ import com.biganto.visual.roompark.util.monades.ExceptionString
import
com.biganto.visual.roompark.util.view_utils.snackbar.ISnackBarProvider
import
com.biganto.visual.roompark.util.view_utils.snackbar.ISnackBarProvider
import
com.hannesdorfmann.mosby3.mvi.MviBasePresenter
import
com.hannesdorfmann.mosby3.mvi.MviBasePresenter
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.disposables.CompositeDisposable
import
timber.log.Timber
/**
/**
* Created by Vladislav Bogdashkin on 28.05.2018.
* Created by Vladislav Bogdashkin on 28.05.2018.
...
@@ -47,7 +48,14 @@ abstract class BigantoBaseController<VS : BigantoBaseViewState,V: BigantoBaseCon
...
@@ -47,7 +48,14 @@ abstract class BigantoBaseController<VS : BigantoBaseViewState,V: BigantoBaseCon
lateinit
var
toolBar
:
ICollapsingToolBar
lateinit
var
toolBar
:
ICollapsingToolBar
lateinit
var
snackbar
:
ISnackBarProvider
lateinit
var
snackbar
:
ISnackBarProvider
override
fun
onAttach
(
view
:
View
)
{
Timber
.
d
(
"On Attach"
)
super
.
onAttach
(
view
)
}
override
fun
onDetach
(
view
:
View
)
{
override
fun
onDetach
(
view
:
View
)
{
Timber
.
d
(
"On Detach"
)
detachDisposable
.
clear
()
detachDisposable
.
clear
()
super
.
onDetach
(
view
)
super
.
onDetach
(
view
)
}
}
...
...
app/src/main/java/com/biganto/visual/roompark/conductor/BigantoBasePresenter.kt
View file @
5d7e5a33
...
@@ -8,6 +8,7 @@ import com.hannesdorfmann.mosby3.mvi.MviBasePresenter
...
@@ -8,6 +8,7 @@ import com.hannesdorfmann.mosby3.mvi.MviBasePresenter
import
com.hannesdorfmann.mosby3.mvp.MvpView
import
com.hannesdorfmann.mosby3.mvp.MvpView
import
com.jakewharton.rxrelay2.PublishRelay
import
com.jakewharton.rxrelay2.PublishRelay
import
io.reactivex.Observable
import
io.reactivex.Observable
import
timber.log.Timber
/**
/**
* Created by Vladislav Bogdashkin on 30.09.2019.
* Created by Vladislav Bogdashkin on 30.09.2019.
...
@@ -27,16 +28,20 @@ abstract class BigantoBasePresenter<V : MvpView, VS>
...
@@ -27,16 +28,20 @@ abstract class BigantoBasePresenter<V : MvpView, VS>
open
fun
vsByCode
(
code
:
Int
)
=
defaultErrorViewStateHandler
()
open
fun
vsByCode
(
code
:
Int
)
=
defaultErrorViewStateHandler
()
open
fun
vsByThrowable
(
t
:
Throwable
)
=
defaultErrorViewStateHandler
()
open
fun
vsByThrowable
(
t
:
Throwable
)
=
defaultErrorViewStateHandler
()
open
fun
parseError
(
t
:
Throwable
):
VS
=
open
fun
parseError
(
t
:
Throwable
)
:
VS
=
when
(
t
)
{
when
(
t
)
{
is
CustomApiException
->
parseError
(
t
)
is
CustomApiException
->{
is
NoNetworkException
->
parseError
(
t
)
Timber
.
d
(
"CustomApiException ${t.messageStringId} / ${t.customMessage}"
)
else
->
parseError
(
t
)
parse
(
t
)
}
is
NoNetworkException
->
parse
(
t
)
else
->
parse
(
t
)
}
}
private
fun
parse
Error
(
e
:
CustomApiException
)
=
onCodeReturn
(
e
)
private
fun
parse
(
e
:
CustomApiException
)
=
onCodeReturn
(
e
)
private
fun
parse
Error
(
e
:
NoNetworkException
)
=
onNoNetwork
(
e
)
private
fun
parse
(
e
:
NoNetworkException
)
=
onNoNetwork
(
e
)
private
fun
parse
Error
(
e
:
Exception
)
=
onRandomError
(
e
)
private
fun
parse
(
e
:
Throwable
)
=
onRandomError
(
e
)
open
fun
onRandomError
(
t
:
Throwable
):
VS
=
open
fun
onRandomError
(
t
:
Throwable
):
VS
=
vsByThrowable
(
t
).
invoke
(
vsByThrowable
(
t
).
invoke
(
...
@@ -48,7 +53,11 @@ abstract class BigantoBasePresenter<V : MvpView, VS>
...
@@ -48,7 +53,11 @@ abstract class BigantoBasePresenter<V : MvpView, VS>
ExceptionString
(
R
.
string
.
no_network_error
,
null
)
ExceptionString
(
R
.
string
.
no_network_error
,
null
)
)
)
private
fun
onCodeReturn
(
e
:
CustomApiException
):
VS
=
private
fun
onCodeReturn
(
e
:
CustomApiException
):
VS
{
vsByCode
(
e
.
code
).
invoke
(
ExceptionString
(
e
))
Timber
.
d
(
"2 CustomApiException ${e.messageStringId} / ${e.customMessage}"
)
val
errst
=
ExceptionString
(
e
.
messageStringId
,
e
.
customMessage
)
Timber
.
d
(
"ExceptionString ${errst} / ${errst}"
)
return
vsByCode
(
e
.
code
).
invoke
(
errst
)
}
}
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/data/local/UserHolder.kt
View file @
5d7e5a33
package
com.biganto.visual.roompark.data.local
package
com.biganto.visual.roompark.data.local
import
android.content.Context
import
android.content.Context
import
com.afollestad.rxkprefs.Pref
import
com.afollestad.rxkprefs.rxkPrefs
import
com.afollestad.rxkprefs.rxkPrefs
import
com.biganto.visual.androidplayer.data.repository.local.ILocalStore
import
com.biganto.visual.androidplayer.data.repository.local.ILocalStore
import
dagger.Binds
import
dagger.Binds
...
@@ -28,6 +29,8 @@ class UserHolder @Inject constructor(val context : Context) : ILocalStore
...
@@ -28,6 +29,8 @@ class UserHolder @Inject constructor(val context : Context) : ILocalStore
}
}
private
val
prefs
=
rxkPrefs
(
context
)
private
val
prefs
=
rxkPrefs
(
context
)
private
val
userSession
:
Pref
<
String
>
=
prefs
.
string
(
RECENT_UUID_KEY
,
EMPTY_PREF_VALUE_KEY
)
companion
object
{
companion
object
{
const
val
RECENT_UUID_KEY
=
"com.biganto.visual.androidplayer.LAST_USER_UUD"
const
val
RECENT_UUID_KEY
=
"com.biganto.visual.androidplayer.LAST_USER_UUD"
const
val
EMPTY_PREF_VALUE_KEY
=
"NO_ACTIVE_SESSION"
const
val
EMPTY_PREF_VALUE_KEY
=
"NO_ACTIVE_SESSION"
...
@@ -46,15 +49,19 @@ class UserHolder @Inject constructor(val context : Context) : ILocalStore
...
@@ -46,15 +49,19 @@ class UserHolder @Inject constructor(val context : Context) : ILocalStore
.
observe
()
.
observe
()
override
fun
recentUser
():
Observable
<
in
UserState
>
=
override
fun
recentUser
():
Observable
<
in
UserState
>
=
prefs
.
string
(
RECENT_UUID_KEY
,
EMPTY_PREF_VALUE_KEY
)
userSession
.
observe
()
.
observe
()
.
map
{
.
map
{
Timber
.
d
(
" AUTH VALUE: $it"
)
if
(
it
==
EMPTY_PREF_VALUE_KEY
)
return
@map
UserState
.
NotAuthenticated
()
if
(
it
==
EMPTY_PREF_VALUE_KEY
)
return
@map
UserState
.
NotAuthenticated
()
else
return
@map
UserState
.
Authenticated
(
it
)
else
return
@map
UserState
.
Authenticated
(
it
)
}
}
override
fun
setRecentUser
(
uuid
:
String
?)
=
override
fun
setRecentUser
(
uuid
:
String
?)
=
Completable
.
fromObservable
(
prefs
.
string
(
RECENT_UUID_KEY
,
uuid
?:
EMPTY_PREF_VALUE_KEY
).
observe
())
Completable
.
defer
{
Completable
.
fromCallable
{
userSession
.
set
(
uuid
?:
EMPTY_PREF_VALUE_KEY
)
}
.
doOnComplete
{
Timber
.
d
(
"complete save null value"
)
}
}
}
}
sealed
class
UserState
{
sealed
class
UserState
{
...
...
app/src/main/java/com/biganto/visual/roompark/data/repository/api/retrofit/IRoomParkMobileApi.kt
View file @
5d7e5a33
...
@@ -3,9 +3,7 @@ package com.biganto.visual.roompark.data.repository.api.retrofit
...
@@ -3,9 +3,7 @@ package com.biganto.visual.roompark.data.repository.api.retrofit
import
com.biganto.visual.roompark.data.repository.api.retrofit.raw.*
import
com.biganto.visual.roompark.data.repository.api.retrofit.raw.*
import
io.reactivex.Observable
import
io.reactivex.Observable
import
retrofit2.Response
import
retrofit2.Response
import
retrofit2.http.GET
import
retrofit2.http.*
import
retrofit2.http.POST
import
retrofit2.http.Query
/**
/**
...
@@ -133,12 +131,13 @@ interface IRoomParkMobileApi{
...
@@ -133,12 +131,13 @@ interface IRoomParkMobileApi{
@POST
(
"$API_URL$AUTH_METHOD$DELIMITER"
)
@POST
(
"$API_URL$AUTH_METHOD$DELIMITER"
)
@FormUrlEncoded
fun
authoriz
(
fun
authoriz
(
@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
(
EMAIL_AUTH_PARAM
)
email
:
String
,
@
Field
(
EMAIL_AUTH_PARAM
)
email
:
String
,
@
Query
(
PASSWORD_AUTH_PARAM
)
pwd
:
String
@
Field
(
PASSWORD_AUTH_PARAM
)
pwd
:
String
):
Observable
<
Response
<
AuthRaw
>>
):
Observable
<
Response
<
AuthRaw
>>
...
...
app/src/main/java/com/biganto/visual/roompark/data/repository/api/retrofit/util/CustomExceptionDeserializer.kt
View file @
5d7e5a33
...
@@ -2,12 +2,7 @@ package com.biganto.visual.roompark.data.repository.api.retrofit.util
...
@@ -2,12 +2,7 @@ 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.retrofit.raw.ErrorRaw
import
com.biganto.visual.roompark.domain.custom_exception.parseException
import
com.biganto.visual.roompark.domain.custom_exception.parseException
import
com.google.gson.Gson
import
com.google.gson.*
import
com.google.gson.JsonDeserializationContext
import
com.google.gson.JsonDeserializer
import
com.google.gson.JsonElement
import
org.json.JSONArray
import
org.json.JSONObject
import
timber.log.Timber
import
timber.log.Timber
import
java.lang.reflect.Type
import
java.lang.reflect.Type
...
@@ -23,9 +18,9 @@ class CustomExceptionDeserializer<T> : JsonDeserializer<T> {
...
@@ -23,9 +18,9 @@ class CustomExceptionDeserializer<T> : JsonDeserializer<T> {
//region valid case
//region valid case
when
(
json
){
when
(
json
){
is
J
SON
Object
->
if
(!
json
.
asJsonObject
.
keySet
().
contains
(
"errors"
))
is
J
son
Object
->
if
(!
json
.
asJsonObject
.
keySet
().
contains
(
"errors"
))
return
Gson
().
newBuilder
().
create
().
fromJson
(
json
,
typeOfT
)
return
Gson
().
newBuilder
().
create
().
fromJson
(
json
,
typeOfT
)
is
J
SON
Array
->
return
Gson
().
newBuilder
().
create
().
fromJson
(
json
,
typeOfT
)
is
J
son
Array
->
return
Gson
().
newBuilder
().
create
().
fromJson
(
json
,
typeOfT
)
}
}
//endregion valid case
//endregion valid case
...
@@ -35,10 +30,10 @@ class CustomExceptionDeserializer<T> : JsonDeserializer<T> {
...
@@ -35,10 +30,10 @@ class CustomExceptionDeserializer<T> : JsonDeserializer<T> {
Timber
.
w
(
"api errorlist: $errorList"
)
Timber
.
w
(
"api errorlist: $errorList"
)
when
(
json
)
{
when
(
json
)
{
is
JSON
Array
->
errorList
.
asJsonArray
.
forEach
{
is
Json
Array
->
errorList
.
asJsonArray
.
forEach
{
vals
.
add
(
ctx
.
deserialize
<
T
>(
it
,
ErrorRaw
::
class
.
java
)
as
ErrorRaw
)
vals
.
add
(
ctx
.
deserialize
<
T
>(
it
,
ErrorRaw
::
class
.
java
)
as
ErrorRaw
)
}
}
is
J
SON
Object
->
json
.
asJsonObject
.
get
(
"errors"
).
asJsonArray
.
forEach
{
is
J
son
Object
->
json
.
asJsonObject
.
get
(
"errors"
).
asJsonArray
.
forEach
{
vals
.
add
(
ctx
.
deserialize
<
T
>(
it
,
ErrorRaw
::
class
.
java
)
as
ErrorRaw
)
vals
.
add
(
ctx
.
deserialize
<
T
>(
it
,
ErrorRaw
::
class
.
java
)
as
ErrorRaw
)
}
}
else
->
throw
RuntimeException
(
"Unexpected JSON type: "
+
json
.
javaClass
)
else
->
throw
RuntimeException
(
"Unexpected JSON type: "
+
json
.
javaClass
)
...
...
app/src/main/java/com/biganto/visual/roompark/di/dagger/ContextModule.kt
View file @
5d7e5a33
...
@@ -59,7 +59,8 @@ class AuthContractModule @Inject constructor(
...
@@ -59,7 +59,8 @@ class AuthContractModule @Inject constructor(
api
.
authenticate
(
email
,
password
)
api
.
authenticate
(
email
,
password
)
.
map
(
::
fromRaw
)
.
map
(
::
fromRaw
)
.
flatMap
{
db
.
upsertUser
(
it
)
}
.
flatMap
{
db
.
upsertUser
(
it
)
}
.
doOnNext
{
local
.
setRecentUser
(
it
.
uuid
.
toString
())
}
.
doOnNext
{
Timber
.
d
(
"user id: ${it.uuid}"
)}
.
doOnNext
{
local
.
setRecentUser
(
it
.
uuid
.
toString
()).
blockingAwait
()
}
.
map
(
::
fromEntity
)
.
map
(
::
fromEntity
)
override
fun
validateAuthState
():
Observable
<
Boolean
>
=
local
.
recentUser
()
override
fun
validateAuthState
():
Observable
<
Boolean
>
=
local
.
recentUser
()
...
@@ -68,5 +69,6 @@ class AuthContractModule @Inject constructor(
...
@@ -68,5 +69,6 @@ class AuthContractModule @Inject constructor(
is
UserState
.
Authenticated
->
true
is
UserState
.
Authenticated
->
true
else
->
false
else
->
false
}
}
}
}
}
}
app/src/main/java/com/biganto/visual/roompark/domain/interactor/settings.kt
View file @
5d7e5a33
...
@@ -3,7 +3,9 @@ package com.biganto.visual.roompark.domain.interactor
...
@@ -3,7 +3,9 @@ package com.biganto.visual.roompark.domain.interactor
import
com.biganto.visual.roompark.domain.model.CachedDataModel
import
com.biganto.visual.roompark.domain.model.CachedDataModel
import
com.biganto.visual.roompark.domain.model.PushSwitchModel
import
com.biganto.visual.roompark.domain.model.PushSwitchModel
import
com.biganto.visual.roompark.domain.model.SettingsModel
import
com.biganto.visual.roompark.domain.model.SettingsModel
import
com.biganto.visual.roompark.domain.use_case.AuthUseCase
import
io.reactivex.Observable
import
io.reactivex.Observable
import
io.reactivex.schedulers.Schedulers
import
javax.inject.Inject
import
javax.inject.Inject
/**
/**
...
@@ -11,10 +13,13 @@ import javax.inject.Inject
...
@@ -11,10 +13,13 @@ import javax.inject.Inject
*/
*/
class
SettingsInteractor
@Inject
constructor
(
class
SettingsInteractor
@Inject
constructor
(
private
val
auth
:
AuthUseCase
){
){
fun
fetchSettings
():
Observable
<
SettingsModel
>
=
Observable
.
just
(
sampleSettings
)
fun
fetchSettings
():
Observable
<
SettingsModel
>
=
Observable
.
just
(
sampleSettings
)
fun
signOut
()
=
auth
.
signOut
().
subscribeOn
(
Schedulers
.
io
())
companion
object
{
companion
object
{
...
...
app/src/main/java/com/biganto/visual/roompark/domain/use_case/authUseCase.kt
View file @
5d7e5a33
...
@@ -10,11 +10,9 @@ import javax.inject.Inject
...
@@ -10,11 +10,9 @@ import javax.inject.Inject
class
AuthUseCase
@Inject
constructor
(
class
AuthUseCase
@Inject
constructor
(
private
val
authContract
:
AuthContract
private
val
authContract
:
AuthContract
){
){
fun
validateAuth
()
=
authContract
.
validateAuthState
()
fun
validateAuth
()
=
authContract
.
validateAuthState
()
fun
signIn
(
login
:
String
,
pwd
:
String
)
=
authContract
.
signIn
(
login
,
pwd
)
fun
signIn
(
login
:
String
,
pwd
:
String
)
=
authContract
.
signIn
(
login
,
pwd
)
fun
signOut
()
=
authContract
.
signOut
()
}
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/auth/ScreenController.kt
View file @
5d7e5a33
...
@@ -3,6 +3,7 @@ package com.biganto.visual.roompark.presentation.screen.auth
...
@@ -3,6 +3,7 @@ package com.biganto.visual.roompark.presentation.screen.auth
import
android.view.View
import
android.view.View
import
butterknife.BindView
import
butterknife.BindView
import
com.biganto.visual.roompark.R
import
com.biganto.visual.roompark.R
import
com.biganto.visual.roompark.base.IBottomNavigation
import
com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.conductor.BigantoBaseController
import
com.biganto.visual.roompark.conductor.BigantoBaseController
...
@@ -11,8 +12,11 @@ import com.bluelinelabs.conductor.RouterTransaction
...
@@ -11,8 +12,11 @@ import com.bluelinelabs.conductor.RouterTransaction
import
com.google.android.material.button.MaterialButton
import
com.google.android.material.button.MaterialButton
import
com.google.android.material.textfield.TextInputLayout
import
com.google.android.material.textfield.TextInputLayout
import
com.jakewharton.rxbinding3.view.clicks
import
com.jakewharton.rxbinding3.view.clicks
import
com.jakewharton.rxbinding3.widget.textChanges
import
io.reactivex.Observable
import
io.reactivex.Observable
import
io.reactivex.android.schedulers.AndroidSchedulers
import
timber.log.Timber
import
timber.log.Timber
import
java.util.concurrent.TimeUnit
import
javax.inject.Inject
import
javax.inject.Inject
/**
/**
...
@@ -24,31 +28,64 @@ class AuthScreenController :
...
@@ -24,31 +28,64 @@ class AuthScreenController :
,
AuthScreen
,
AuthScreen
,
AuthScreenPresenter
>()
,
AuthScreenPresenter
>()
,
AuthScreen
{
,
AuthScreen
{
override
fun
onViewBound
(
v
:
View
)
{
override
fun
onViewBound
(
v
:
View
)
{
}
toolBar
.
hideAll
()
bottomNavigation
.
hide
()
@BindView
(
R
.
id
.
login_text_input
)
lateinit
var
loginInput
:
TextInputLayout
}
@BindView
(
R
.
id
.
password_text_input
)
lateinit
var
pwdInput
:
TextInputLayout
@BindView
(
R
.
id
.
sign_in_button
)
lateinit
var
signInButton
:
MaterialButton
@BindView
(
R
.
id
.
login_text_input
)
lateinit
var
loginInput
:
TextInputLayout
@BindView
(
R
.
id
.
password_text_input
)
lateinit
var
pwdInput
:
TextInputLayout
@BindView
(
R
.
id
.
sign_in_button
)
lateinit
var
signInButton
:
MaterialButton
override
fun
tryAuth
():
Observable
<
AuthInputModel
>
=
override
fun
tryAuth
():
Observable
<
AuthInputModel
>
=
signInButton
.
clicks
()
signInButton
.
clicks
()
.
map
<
AuthInputModel
>{
AuthInputModel
(
loginInput
.
editText
?.
text
?.
toString
()
?:
""
.
debounce
(
200L
,
TimeUnit
.
MILLISECONDS
)
,
pwdInput
.
editText
?.
text
?.
toString
()
?:
""
)
.
doOnNext
{
signInButton
.
hideKeyboard
()
}
}
.
map
<
AuthInputModel
>
{
AuthInputModel
(
loginInput
.
editText
?.
text
?.
toString
()
?:
""
,
pwdInput
.
editText
?.
text
?.
toString
()
?:
""
)
}
.
observeOn
(
AndroidSchedulers
.
mainThread
())
override
fun
injectDependencies
()
{
override
fun
injectDependencies
()
{
getComponent
()
getComponent
()
}
}
override
fun
onAttach
(
view
:
View
)
{
super
.
onAttach
(
view
)
detachDisposable
.
addAll
(
loginInput
.
editText
?.
textChanges
()
?.
doOnNext
{
Timber
.
d
(
"loginInput.isErrorEnabled ${loginInput.isErrorEnabled}"
)}
?.
filter
{
loginInput
.
isErrorEnabled
}
?.
subscribe
{
Timber
.
d
(
"got key $it"
)
loginInput
.
isErrorEnabled
=
false
loginInput
.
error
=
null
signInButton
.
isEnabled
=
true
},
pwdInput
.
editText
?.
textChanges
()
?.
filter
{
pwdInput
.
isErrorEnabled
}
?.
subscribe
{
pwdInput
.
isErrorEnabled
=
false
signInButton
.
isEnabled
=
true
}
)
}
@Inject
@Inject
override
lateinit
var
injectedPresenter
:
AuthScreenPresenter
lateinit
var
bottomNavigation
:
IBottomNavigation
@Inject
override
lateinit
var
injectedPresenter
:
AuthScreenPresenter
// @Inject
// @Inject
// lateinit var snacky:ISnackBarProvider
// lateinit var snacky:ISnackBarProvider
...
@@ -63,8 +100,6 @@ class AuthScreenController :
...
@@ -63,8 +100,6 @@ class AuthScreenController :
// @Inject
// @Inject
// lateinit var ac: RoomParkMainActivity
// lateinit var ac: RoomParkMainActivity
override
fun
render
(
viewState
:
AuthScreenViewState
)
{
override
fun
render
(
viewState
:
AuthScreenViewState
)
{
super
.
render
(
viewState
)
super
.
render
(
viewState
)
Timber
.
d
(
"Render state $viewState"
)
Timber
.
d
(
"Render state $viewState"
)
...
@@ -74,6 +109,8 @@ class AuthScreenController :
...
@@ -74,6 +109,8 @@ class AuthScreenController :
is
AuthScreenViewState
.
SignedIn
->
render
(
viewState
)
is
AuthScreenViewState
.
SignedIn
->
render
(
viewState
)
is
AuthScreenViewState
.
SignInError
->
render
(
viewState
)
is
AuthScreenViewState
.
SignInError
->
render
(
viewState
)
is
AuthScreenViewState
.
SomeError
->
render
(
viewState
)
is
AuthScreenViewState
.
SomeError
->
render
(
viewState
)
is
AuthScreenViewState
.
WrongLogin
->
render
(
viewState
)
is
AuthScreenViewState
.
WrongPassword
->
render
(
viewState
)
}
}
}
}
...
@@ -97,6 +134,27 @@ class AuthScreenController :
...
@@ -97,6 +134,27 @@ class AuthScreenController :
signInButton
.
isEnabled
=
true
signInButton
.
isEnabled
=
true
}
}
private
fun
render
(
viewState
:
AuthScreenViewState
.
WrongLogin
){
// showError(viewState.exception)
loginInput
.
isErrorEnabled
=
true
loginInput
.
errorIconDrawable
=
null
viewState
.
exception
.
selectHandler
(
{
strId
->
loginInput
.
error
=
resources
?.
getString
(
strId
)},
{
message
->
loginInput
.
error
=
message
}
)
}
private
fun
render
(
viewState
:
AuthScreenViewState
.
WrongPassword
){
pwdInput
.
isErrorEnabled
=
true
pwdInput
.
errorIconDrawable
=
null
viewState
.
exception
.
selectHandler
(
{
strId
->
pwdInput
.
error
=
resources
?.
getString
(
strId
)},
{
message
->
pwdInput
.
error
=
message
}
)
}
private
fun
render
(
viewState
:
AuthScreenViewState
.
SomeError
)
=
private
fun
render
(
viewState
:
AuthScreenViewState
.
SomeError
)
=
showError
(
viewState
.
exception
)
showError
(
viewState
.
exception
)
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/auth/ScreenDI.kt
View file @
5d7e5a33
package
com.biganto.visual.roompark.presentation.screen.auth
package
com.biganto.visual.roompark.presentation.screen.auth
import
android.content.Context
import
android.content.Context
import
com.biganto.visual.roompark.base.IBottomNavigation
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.base.RoomParkMainActivity
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.db.requrey.DbModule
import
com.biganto.visual.roompark.data.repository.db.requrey.DbModule
...
@@ -43,4 +44,8 @@ abstract class AuthScreenModule{
...
@@ -43,4 +44,8 @@ abstract class AuthScreenModule{
@Binds
@Binds
abstract
fun
provideAuth
(
contract
:
AuthContractModule
):
AuthContract
abstract
fun
provideAuth
(
contract
:
AuthContractModule
):
AuthContract
@PerScreen
@Binds
abstract
fun
provideBottomNavigation
(
activitiy
:
RoomParkMainActivity
):
IBottomNavigation
}
}
app/src/main/java/com/biganto/visual/roompark/presentation/screen/auth/ScreenPresenter.kt
View file @
5d7e5a33
...
@@ -3,6 +3,7 @@ package com.biganto.visual.roompark.presentation.screen.auth
...
@@ -3,6 +3,7 @@ package com.biganto.visual.roompark.presentation.screen.auth
import
com.biganto.visual.roompark.conductor.BigantoBasePresenter
import
com.biganto.visual.roompark.conductor.BigantoBasePresenter
import
com.biganto.visual.roompark.domain.interactor.AuthInteractor
import
com.biganto.visual.roompark.domain.interactor.AuthInteractor
import
com.biganto.visual.roompark.util.monades.ExceptionString
import
com.biganto.visual.roompark.util.monades.ExceptionString
import
io.reactivex.Observable
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.schedulers.Schedulers
import
io.reactivex.schedulers.Schedulers
import
timber.log.Timber
import
timber.log.Timber
...
@@ -18,32 +19,47 @@ class AuthScreenPresenter @Inject constructor(
...
@@ -18,32 +19,47 @@ class AuthScreenPresenter @Inject constructor(
)
)
:
BigantoBasePresenter
<
AuthScreen
,
AuthScreenViewState
>()
{
:
BigantoBasePresenter
<
AuthScreen
,
AuthScreenViewState
>()
{
override
fun
attachView
(
view
:
AuthScreen
)
{
super
.
attachView
(
view
)
Timber
.
d
(
"on AttachView"
)
restoreStateObservable
.
accept
(
AuthScreenViewState
.
Idle
())
}
override
fun
detachView
()
{
super
.
detachView
()
Timber
.
d
(
"on DetachView"
)
restoreStateObservable
}
override
fun
defaultErrorViewStateHandler
()
=
override
fun
defaultErrorViewStateHandler
()
=
{
e
:
ExceptionString
->
AuthScreenViewState
.
SomeError
(
e
)}
{
e
:
ExceptionString
->
AuthScreenViewState
.
SomeError
(
e
)}
override
fun
vsByCode
(
code
:
Int
):
(
ExceptionString
)
->
AuthScreenViewState
=
override
fun
vsByCode
(
code
:
Int
):
(
ExceptionString
)
->
AuthScreenViewState
=
when
(
code
)
{
when
(
code
)
{
101
->
{
e
:
ExceptionString
->
AuthScreenViewState
.
SignInError
(
e
)}
101
->
{
e
:
ExceptionString
->
AuthScreenViewState
.
SignInError
(
e
)}
111
->
{
e
:
ExceptionString
->
AuthScreenViewState
.
WrongLogin
(
e
)}
112
->
{
e
:
ExceptionString
->
AuthScreenViewState
.
WrongPassword
(
e
)}
else
->
{
e
:
ExceptionString
->
AuthScreenViewState
.
SomeError
(
e
)}
else
->
{
e
:
ExceptionString
->
AuthScreenViewState
.
SomeError
(
e
)}
}
}
override
fun
bindIntents
()
{
override
fun
bindIntents
()
{
val
onAuth
=
intent
(
AuthScreen
::
tryAuth
)
val
onAuth
=
intent
(
AuthScreen
::
tryAuth
)
.
flatMap
<
AuthScreenViewState
>
{
model
->
.
flatMap
<
AuthScreenViewState
>
{
model
->
interactor
.
signIn
(
model
.
login
,
model
.
pwd
)
interactor
.
signIn
(
model
.
login
,
model
.
pwd
)
.
doOnNext
{
Timber
.
d
(
"auth returned $it"
)
}
.
doOnNext
{
Timber
.
d
(
"auth returned $it"
)
}
.
map
{
it
}
.
map
{
it
}
.
map
<
AuthScreenViewState
>
{
AuthScreenViewState
.
SignedIn
()
}
.
map
{
AuthScreenViewState
.
SignedIn
()
}
.
onErrorReturn
{
parseError
(
it
)}
.
startWith
(
Observable
.
just
(
AuthScreenViewState
.
Authorization
()))
}
}
// .startWith(Observable.just(AuthScreenViewState.Authorization()))
val
state
=
restoreStateObservable
val
state
=
restoreStateObservable
.
mergeWith
(
onAuth
)
.
mergeWith
(
onAuth
)
.
doOnError
{
Timber
.
e
(
it
)
}
.
doOnError
{
Timber
.
e
(
it
)
}
.
onErrorReturn
(
::
parseError
)
.
onErrorReturn
(
::
parseError
)
.
subscribeOn
(
Schedulers
.
single
())
.
subscribeOn
(
Schedulers
.
single
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/auth/ScreenViewState.kt
View file @
5d7e5a33
...
@@ -13,4 +13,7 @@ sealed class AuthScreenViewState : BigantoBaseViewState() {
...
@@ -13,4 +13,7 @@ sealed class AuthScreenViewState : BigantoBaseViewState() {
class
SignedIn
:
AuthScreenViewState
()
class
SignedIn
:
AuthScreenViewState
()
class
SignInError
(
val
exception
:
ExceptionString
)
:
AuthScreenViewState
()
class
SignInError
(
val
exception
:
ExceptionString
)
:
AuthScreenViewState
()
class
SomeError
(
val
exception
:
ExceptionString
)
:
AuthScreenViewState
()
class
SomeError
(
val
exception
:
ExceptionString
)
:
AuthScreenViewState
()
class
WrongLogin
(
val
exception
:
ExceptionString
)
:
AuthScreenViewState
()
class
WrongPassword
(
val
exception
:
ExceptionString
)
:
AuthScreenViewState
()
}
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/home/home_routing/HomeBottomNavigationController.kt
View file @
5d7e5a33
package
com.biganto.visual.roompark.presentation.screen.home.home_routing
package
com.biganto.visual.roompark.presentation.screen.home.home_routing
import
android.os.Bundle
import
android.os.Bundle
import
android.util.Log
import
android.view.View
import
android.view.View
import
androidx.annotation.IdRes
import
androidx.annotation.IdRes
import
androidx.annotation.NonNull
import
androidx.annotation.NonNull
...
@@ -43,7 +42,7 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
...
@@ -43,7 +42,7 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
}
}
override
fun
getStartupMenuId
():
Int
=
override
fun
getStartupMenuId
():
Int
=
args
.
getInt
(
OPEN_CHILD_CONTROLLER_KEY
,
R
.
id
.
tab_feeds
)
args
.
getInt
(
OPEN_CHILD_CONTROLLER_KEY
,
R
.
id
.
tab_feeds
)
@Inject
@Inject
...
@@ -56,40 +55,34 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
...
@@ -56,40 +55,34 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
override
lateinit
var
injectedPresenter
:
HomeScreenPresenter
override
lateinit
var
injectedPresenter
:
HomeScreenPresenter
fun
getComponent
()
=
DaggerHomeScreenComponent
fun
getComponent
()
=
DaggerHomeScreenComponent
.
factory
()
.
factory
()
.
create
(
RoomParkApplication
.
component
,
activity
as
RoomParkMainActivity
)
.
create
(
RoomParkApplication
.
component
,
activity
as
RoomParkMainActivity
)
.
inject
(
this
)
.
inject
(
this
)
override
fun
render
(
viewState
:
HomeScreenViewState
)
{
override
fun
render
(
viewState
:
HomeScreenViewState
)
{
when
(
viewState
)
{
when
(
viewState
)
{
is
HomeScreenViewState
.
Idle
->
render
(
viewState
)
is
HomeScreenViewState
.
Idle
->
render
(
viewState
)
is
HomeScreenViewState
.
ToScreen
->
render
(
viewState
)
is
HomeScreenViewState
.
ToScreen
->
render
(
viewState
)
is
HomeScreenViewState
.
SomeError
->
render
(
viewState
)
is
HomeScreenViewState
.
SomeError
->
render
(
viewState
)
}
}
}
}
private
fun
render
(
viewState
:
HomeScreenViewState
.
Idle
){
private
fun
render
(
viewState
:
HomeScreenViewState
.
Idle
)
{
}
}
private
fun
render
(
viewState
:
HomeScreenViewState
.
SomeError
)
=
private
fun
render
(
viewState
:
HomeScreenViewState
.
SomeError
)
=
showError
(
viewState
.
exception
)
showError
(
viewState
.
exception
)
private
fun
render
(
viewState
:
HomeScreenViewState
.
ToScreen
){
private
fun
render
(
viewState
:
HomeScreenViewState
.
ToScreen
)
{
// snacky.showSnackBar("lul")
// snacky.showSnackBar("lul")
}
}
override
fun
getLayoutId
()
=
R
.
layout
.
tab_routing_screen_view
override
fun
getLayoutId
()
=
R
.
layout
.
tab_routing_screen_view
override
val
tag
:
String
override
val
tag
:
String
...
@@ -100,7 +93,8 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
...
@@ -100,7 +93,8 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
bottomNavigation
.
show
()
bottomNavigation
.
show
()
Timber
.
d
(
" onViewBound: ${this::class}"
)
Timber
.
d
(
" onViewBound: ${this::class}"
)
bottomNavigationView
=
((
activity
as
RoomParkMainActivity
)
as
IBottomNavigation
).
bottomNavigation
bottomNavigationView
=
((
activity
as
RoomParkMainActivity
)
as
IBottomNavigation
).
bottomNavigation
bottomNavigationView
.
visibility
=
BottomNavigationView
.
VISIBLE
bottomNavigationView
.
visibility
=
BottomNavigationView
.
VISIBLE
controllerContainer
=
view
.
findViewById
(
R
.
id
.
tabContainer
)
controllerContainer
=
view
.
findViewById
(
R
.
id
.
tabContainer
)
bottomNavigationView
.
setOnNavigationItemSelectedListener
{
item
->
bottomNavigationView
.
setOnNavigationItemSelectedListener
{
item
->
...
@@ -146,19 +140,20 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
...
@@ -146,19 +140,20 @@ class HomeBottomNavigationController(@IdRes toPage: Int = R.id.tab_feeds)
val
childRouter
=
getChildRouter
(
currentlySelectedItemId
)
val
childRouter
=
getChildRouter
(
currentlySelectedItemId
)
Timber
.
d
(
"in back stack - ${childRouter?.backstackSize}"
)
Timber
.
d
(
"in back stack - ${childRouter?.backstackSize}"
)
if
(
childRouter
!=
null
)
{
if
(
childRouter
!=
null
)
{
val
backStackSizeCondition
=
childRouter
.
backstackSize
<
0
if
(
childRouter
.
backstackSize
<
2
)
return
false
val
backStackResult
=
childRouter
.
handleBack
()
if
(
backStackResult
if
(
childRouter
.
handleBack
())
&&
backStackSizeCondition
)
navigateTo
(
getControllerFor
(
R
.
id
.
tab_feeds
),
false
)
navigateTo
(
getControllerFor
(
R
.
id
.
tab_feeds
),
false
)
return
backStackResult
return
true
}
else
{
}
else
{
Log
.
e
(
TAG
,
"handleBack called with getChildRouter(currentlySelectedItemId) == null."
,
Timber
.
e
(
IllegalStateException
(
IllegalStateException
(
"handleBack called with getChildRouter(currentlySelectedItemId) == null."
))
"handleBack called with getChildRouter(currentlySelectedItemId) == null."
),
"handleBack called with getChildRouter(currentlySelectedItemId) == null."
)
}
}
return
false
return
false
}
}
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/settings/ScreenContract.kt
View file @
5d7e5a33
package
com.biganto.visual.roompark.presentation.screen.settings
package
com.biganto.visual.roompark.presentation.screen.settings
import
com.biganto.visual.roompark.conductor.BigantoBaseContract
import
com.biganto.visual.roompark.conductor.BigantoBaseContract
import
io.reactivex.Observable
/**
/**
* Created by Vladislav Bogdashkin on 30.09.2019.
* Created by Vladislav Bogdashkin on 30.09.2019.
*/
*/
interface
SettingsScreen
:
BigantoBaseContract
<
SettingsScreenViewState
>
{
interface
SettingsScreen
:
BigantoBaseContract
<
SettingsScreenViewState
>
{
fun
signOut
():
Observable
<
Int
>
}
}
app/src/main/java/com/biganto/visual/roompark/presentation/screen/settings/ScreenController.kt
View file @
5d7e5a33
...
@@ -13,8 +13,14 @@ import com.biganto.visual.roompark.base.RoomParkMainActivity
...
@@ -13,8 +13,14 @@ import com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.conductor.BigantoBaseController
import
com.biganto.visual.roompark.conductor.BigantoBaseController
import
com.biganto.visual.roompark.presentation.screen.settings.util.CahcedListAdapter
import
com.biganto.visual.roompark.presentation.screen.settings.util.CahcedListAdapter
import
com.biganto.visual.roompark.presentation.screen.settings.util.PushListAdapter
import
com.biganto.visual.roompark.presentation.screen.settings.util.PushListAdapter
import
com.biganto.visual.roompark.presentation.screen.splash.SplashScreenController
import
com.biganto.visual.roompark.util.extensions.bytesToSize
import
com.biganto.visual.roompark.util.extensions.bytesToSize
import
com.bluelinelabs.conductor.RouterTransaction
import
com.bluelinelabs.conductor.changehandler.FadeChangeHandler
import
com.google.android.material.textview.MaterialTextView
import
com.google.android.material.textview.MaterialTextView
import
com.jakewharton.rxbinding3.view.clicks
import
io.reactivex.Observable
import
io.reactivex.android.schedulers.AndroidSchedulers
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -28,6 +34,11 @@ class SettingsScreenController :
...
@@ -28,6 +34,11 @@ class SettingsScreenController :
,
SettingsScreenPresenter
>()
,
SettingsScreenPresenter
>()
,
SettingsScreen
{
,
SettingsScreen
{
override
fun
signOut
():
Observable
<
Int
>
=
signOutButton
.
clicks
()
.
map
{
Timber
.
d
(
"Clicked sign out button"
);
1
}
.
observeOn
(
AndroidSchedulers
.
mainThread
())
override
fun
injectDependencies
()
{
override
fun
injectDependencies
()
{
getComponent
()
getComponent
()
}
}
...
@@ -57,6 +68,9 @@ class SettingsScreenController :
...
@@ -57,6 +68,9 @@ class SettingsScreenController :
@BindView
(
R
.
id
.
downloadFlatCardsIcon
)
@BindView
(
R
.
id
.
downloadFlatCardsIcon
)
lateinit
var
flatDownloaderButton
:
ImageView
lateinit
var
flatDownloaderButton
:
ImageView
@BindView
(
R
.
id
.
signOutButton
)
lateinit
var
signOutButton
:
MaterialTextView
private
fun
setToolbar
(){
private
fun
setToolbar
(){
toolBar
.
showAll
()
toolBar
.
showAll
()
...
@@ -94,6 +108,7 @@ class SettingsScreenController :
...
@@ -94,6 +108,7 @@ class SettingsScreenController :
is
SettingsScreenViewState
.
Idle
->
render
(
viewState
)
is
SettingsScreenViewState
.
Idle
->
render
(
viewState
)
is
SettingsScreenViewState
.
LoadSettingsList
->
render
(
viewState
)
is
SettingsScreenViewState
.
LoadSettingsList
->
render
(
viewState
)
is
SettingsScreenViewState
.
SomeError
->
render
(
viewState
)
is
SettingsScreenViewState
.
SomeError
->
render
(
viewState
)
is
SettingsScreenViewState
.
SignOut
->
render
(
viewState
)
}
}
}
}
...
@@ -104,6 +119,13 @@ class SettingsScreenController :
...
@@ -104,6 +119,13 @@ class SettingsScreenController :
}
}
private
fun
render
(
viewState
:
SettingsScreenViewState
.
SignOut
){
router
.
setRoot
(
RouterTransaction
.
with
(
SplashScreenController
())
.
pushChangeHandler
(
FadeChangeHandler
())
.
popChangeHandler
(
FadeChangeHandler
())
)
}
@SuppressLint
(
"SetTextI18n"
)
@SuppressLint
(
"SetTextI18n"
)
private
fun
render
(
viewState
:
SettingsScreenViewState
.
LoadSettingsList
){
private
fun
render
(
viewState
:
SettingsScreenViewState
.
LoadSettingsList
){
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/settings/ScreenDI.kt
View file @
5d7e5a33
...
@@ -2,8 +2,10 @@ package com.biganto.visual.roompark.presentation.screen.settings
...
@@ -2,8 +2,10 @@ package com.biganto.visual.roompark.presentation.screen.settings
import
android.content.Context
import
android.content.Context
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.di.dagger.AppComponent
import
com.biganto.visual.roompark.data.repository.api.retrofit.di.RetrofitModule
import
com.biganto.visual.roompark.di.dagger.PerScreen
import
com.biganto.visual.roompark.data.repository.db.requrey.DbModule
import
com.biganto.visual.roompark.di.dagger.*
import
com.biganto.visual.roompark.domain.contract.AuthContract
import
dagger.Binds
import
dagger.Binds
import
dagger.BindsInstance
import
dagger.BindsInstance
import
dagger.Component
import
dagger.Component
...
@@ -12,7 +14,8 @@ import dagger.Module
...
@@ -12,7 +14,8 @@ import dagger.Module
@PerScreen
@PerScreen
@Component
(
@Component
(
modules
=
[
SettingsScreenModule
::
class
],
modules
=
[
SettingsScreenModule
::
class
,
DataModule
::
class
,
RetrofitModule
::
class
,
AppModule
::
class
,
DbModule
::
class
],
dependencies
=
[
AppComponent
::
class
])
dependencies
=
[
AppComponent
::
class
])
interface
SettingsScreenComponent
{
interface
SettingsScreenComponent
{
...
@@ -34,6 +37,10 @@ abstract class SettingsScreenModule{
...
@@ -34,6 +37,10 @@ abstract class SettingsScreenModule{
@PerScreen
@PerScreen
@Binds
@Binds
abstract
fun
provideContext
(
activity
:
RoomParkMainActivity
):
Context
abstract
fun
provideContext
(
activity
:
RoomParkMainActivity
):
Context
@PerScreen
@Binds
abstract
fun
provideAuth
(
contract
:
AuthContractModule
):
AuthContract
}
}
app/src/main/java/com/biganto/visual/roompark/presentation/screen/settings/ScreenPresenter.kt
View file @
5d7e5a33
...
@@ -3,6 +3,7 @@ package com.biganto.visual.roompark.presentation.screen.settings
...
@@ -3,6 +3,7 @@ package com.biganto.visual.roompark.presentation.screen.settings
import
com.biganto.visual.roompark.conductor.BigantoBasePresenter
import
com.biganto.visual.roompark.conductor.BigantoBasePresenter
import
com.biganto.visual.roompark.domain.interactor.SettingsInteractor
import
com.biganto.visual.roompark.domain.interactor.SettingsInteractor
import
com.biganto.visual.roompark.util.monades.ExceptionString
import
com.biganto.visual.roompark.util.monades.ExceptionString
import
io.reactivex.Observable
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.schedulers.Schedulers
import
io.reactivex.schedulers.Schedulers
import
timber.log.Timber
import
timber.log.Timber
...
@@ -26,10 +27,20 @@ class SettingsScreenPresenter @Inject constructor(
...
@@ -26,10 +27,20 @@ class SettingsScreenPresenter @Inject constructor(
val
fetchSettings
=
interactor
.
fetchSettings
()
val
fetchSettings
=
interactor
.
fetchSettings
()
.
map
{
SettingsScreenViewState
.
LoadSettingsList
(
it
)
}
.
map
{
SettingsScreenViewState
.
LoadSettingsList
(
it
)
}
val
onSignOut
=
intent
(
SettingsScreen
::
signOut
)
.
flatMap
{
interactor
.
signOut
()
.
andThen
(
Observable
.
just
<
SettingsScreenViewState
>(
SettingsScreenViewState
.
SignOut
()))
.
onErrorReturn
(
::
parseError
)
}
val
state
=
restoreStateObservable
val
state
=
restoreStateObservable
.
mergeWith
(
fetchSettings
)
.
mergeWith
(
fetchSettings
)
.
mergeWith
(
onSignOut
)
.
doOnError
{
Timber
.
e
(
it
)}
.
doOnError
{
Timber
.
e
(
it
)}
.
subscribeOn
(
Schedulers
.
io
())
.
subscribeOn
(
Schedulers
.
io
())
.
onErrorReturn
(
::
parseError
)
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
subscribeViewState
(
state
.
cast
(
SettingsScreenViewState
::
class
.
java
),
SettingsScreen
::
render
)
subscribeViewState
(
state
.
cast
(
SettingsScreenViewState
::
class
.
java
),
SettingsScreen
::
render
)
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/settings/ScreenViewState.kt
View file @
5d7e5a33
...
@@ -13,4 +13,5 @@ sealed class SettingsScreenViewState : BigantoBaseViewState() {
...
@@ -13,4 +13,5 @@ sealed class SettingsScreenViewState : BigantoBaseViewState() {
class
Idle
:
SettingsScreenViewState
()
class
Idle
:
SettingsScreenViewState
()
class
LoadSettingsList
(
val
settings
:
SettingsModel
)
:
SettingsScreenViewState
()
class
LoadSettingsList
(
val
settings
:
SettingsModel
)
:
SettingsScreenViewState
()
class
SomeError
(
val
exception
:
ExceptionString
)
:
SettingsScreenViewState
()
class
SomeError
(
val
exception
:
ExceptionString
)
:
SettingsScreenViewState
()
class
SignOut
()
:
SettingsScreenViewState
()
}
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/splash/ScreenController.kt
View file @
5d7e5a33
...
@@ -2,6 +2,7 @@ package com.biganto.visual.roompark.presentation.screen.splash
...
@@ -2,6 +2,7 @@ package com.biganto.visual.roompark.presentation.screen.splash
import
android.view.View
import
android.view.View
import
com.biganto.visual.roompark.R
import
com.biganto.visual.roompark.R
import
com.biganto.visual.roompark.base.IBottomNavigation
import
com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.conductor.BigantoBaseController
import
com.biganto.visual.roompark.conductor.BigantoBaseController
...
@@ -23,6 +24,8 @@ class SplashScreenController :
...
@@ -23,6 +24,8 @@ class SplashScreenController :
override
fun
onViewBound
(
v
:
View
)
{
override
fun
onViewBound
(
v
:
View
)
{
toolBar
.
hideAll
()
bottomNavigation
.
hide
()
}
}
override
fun
injectDependencies
()
{
override
fun
injectDependencies
()
{
...
@@ -46,6 +49,8 @@ class SplashScreenController :
...
@@ -46,6 +49,8 @@ class SplashScreenController :
// @Inject
// @Inject
// lateinit var ac: RoomParkMainActivity
// lateinit var ac: RoomParkMainActivity
@Inject
lateinit
var
bottomNavigation
:
IBottomNavigation
override
fun
render
(
viewState
:
SplashScreenViewState
)
{
override
fun
render
(
viewState
:
SplashScreenViewState
)
{
when
(
viewState
){
when
(
viewState
){
...
@@ -72,8 +77,8 @@ class SplashScreenController :
...
@@ -72,8 +77,8 @@ class SplashScreenController :
private
fun
render
(
viewState
:
SplashScreenViewState
.
ToHomeScreen
){
private
fun
render
(
viewState
:
SplashScreenViewState
.
ToHomeScreen
){
router
.
setRoot
(
RouterTransaction
.
with
(
HomeBottomNavigationController
())
router
.
setRoot
(
RouterTransaction
.
with
(
HomeBottomNavigationController
())
.
popChangeHandler
(
FadeChangeHandler
())
.
popChangeHandler
(
FadeChangeHandler
(
200L
))
.
pushChangeHandler
(
FadeChangeHandler
())
.
pushChangeHandler
(
FadeChangeHandler
(
300L
))
)
)
}
}
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/splash/ScreenDI.kt
View file @
5d7e5a33
package
com.biganto.visual.roompark.presentation.screen.splash
package
com.biganto.visual.roompark.presentation.screen.splash
import
android.content.Context
import
android.content.Context
import
com.biganto.visual.roompark.base.IBottomNavigation
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.base.RoomParkMainActivity
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.db.requrey.DbModule
import
com.biganto.visual.roompark.data.repository.db.requrey.DbModule
...
@@ -50,4 +51,8 @@ abstract class SplashScreenModule{
...
@@ -50,4 +51,8 @@ abstract class SplashScreenModule{
// @Binds
// @Binds
// abstract fun provideToolbar(activitiy: RoomParkMainActivity): ICollapsingToolBar
// abstract fun provideToolbar(activitiy: RoomParkMainActivity): ICollapsingToolBar
@PerScreen
@Binds
abstract
fun
provideBottomNavigation
(
activitiy
:
RoomParkMainActivity
):
IBottomNavigation
}
}
app/src/main/java/com/biganto/visual/roompark/presentation/screen/splash/ScreenPresenter.kt
View file @
5d7e5a33
...
@@ -4,6 +4,9 @@ import com.biganto.visual.roompark.base.RoomParkMainActivity
...
@@ -4,6 +4,9 @@ import com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.conductor.BigantoBasePresenter
import
com.biganto.visual.roompark.conductor.BigantoBasePresenter
import
com.biganto.visual.roompark.domain.interactor.SplashInteractor
import
com.biganto.visual.roompark.domain.interactor.SplashInteractor
import
com.biganto.visual.roompark.util.monades.ExceptionString
import
com.biganto.visual.roompark.util.monades.ExceptionString
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.schedulers.Schedulers
import
java.util.concurrent.TimeUnit
import
javax.inject.Inject
import
javax.inject.Inject
/**
/**
...
@@ -29,7 +32,10 @@ class SplashScreenPresenter @Inject constructor(
...
@@ -29,7 +32,10 @@ class SplashScreenPresenter @Inject constructor(
if
(
it
)
SplashScreenViewState
.
ToHomeScreen
()
if
(
it
)
SplashScreenViewState
.
ToHomeScreen
()
else
SplashScreenViewState
.
ToAuthScreen
()
else
SplashScreenViewState
.
ToAuthScreen
()
}
}
.
delay
(
250
,
TimeUnit
.
MILLISECONDS
)
)
)
.
subscribeOn
(
Schedulers
.
io
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
subscribeViewState
(
state
.
cast
(
SplashScreenViewState
::
class
.
java
),
SplashScreen
::
render
)
subscribeViewState
(
state
.
cast
(
SplashScreenViewState
::
class
.
java
),
SplashScreen
::
render
)
}
}
...
...
app/src/main/java/com/biganto/visual/roompark/util/monades/either.kt
View file @
5d7e5a33
...
@@ -18,7 +18,7 @@ sealed class Either<out E, out V> {
...
@@ -18,7 +18,7 @@ sealed class Either<out E, out V> {
data class
ExceptionString
(
@StringRes
private
val
stringId
:
Int
?,
private
val
message
:
String
?)
{
data class
ExceptionString
(
@StringRes
private
val
stringId
:
Int
?,
private
val
message
:
String
?)
{
val
errorMessage
:
Either
<
Int
,
String
>
fun
selectHandler
(
a1
:(
Int
)->
Unit
,
a2
:(
String
)->
Unit
)
=
fun
selectHandler
(
a1
:(
Int
)->
Unit
,
a2
:(
String
)->
Unit
)
=
when
(
errorMessage
){
when
(
errorMessage
){
...
@@ -27,13 +27,16 @@ data class ExceptionString(@StringRes private val stringId: Int?, private val m
...
@@ -27,13 +27,16 @@ data class ExceptionString(@StringRes private val stringId: Int?, private val m
}
}
constructor
(
e
:
CustomApiException
)
:
this
(
constructor
(
e
:
CustomApiException
)
:
this
(
if
(
e
.
m
essage
!=
null
)
null
else
e
.
messageStringId
,
if
(
e
.
customM
essage
!=
null
)
null
else
e
.
messageStringId
,
if
(
e
.
messageStringId
!=
null
)
null
else
e
.
m
essage
e
.
customM
essage
)
)
init
{
val
errorMessage
:
Either
<
Int
,
String
>
=
if
(
stringId
!=
null
)
Either
.
Left
(
stringId
)
else
Either
.
Right
(
message
!!
)
assert
(
stringId
==
null
&&
message
==
null
)
{
"both values cannot be null!"
}
errorMessage
=
if
(
stringId
!=
null
)
Either
.
Left
(
stringId
)
else
Either
.
Right
(
message
!!
)
// init {
}
// Timber.d(" messages: $stringId / $message")
// if (stringId==null && message==null) throw error{ "both values cannot be null!" }
// errorMessage = if (stringId!=null) Either.Left(stringId) else Either.Right(message!!)
// }
}
}
app/src/main/res/color/sign_in_button_selector.xml
View file @
5d7e5a33
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<selector
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item
android:state_enabled=
"false"
android:color=
"@color/colorAccent"
/>
<item
android:state_enabled=
"false"
android:color=
"@color/colorGray"
/>
<item
android:color=
"@color/colorGray"
/>
<item
android:color=
"@color/colorAccent"
/>
</selector>
</selector>
\ No newline at end of file
app/src/main/res/layout/activity_main.xml
View file @
5d7e5a33
...
@@ -5,7 +5,6 @@
...
@@ -5,7 +5,6 @@
android:id=
"@+id/bottom_drawer_menu"
android:id=
"@+id/bottom_drawer_menu"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
android:fitsSystemWindows=
"true"
tools:context=
".base.RoomParkMainActivity"
>
tools:context=
".base.RoomParkMainActivity"
>
...
@@ -24,11 +23,11 @@
...
@@ -24,11 +23,11 @@
android:clipToPadding=
"true"
android:clipToPadding=
"true"
android:theme=
"@style/ThemeOverlay.AppCompat.Light"
android:theme=
"@style/ThemeOverlay.AppCompat.Light"
app:expanded=
"false"
app:expanded=
"false"
app:liftOnScroll=
"true"
app:layout_behavior=
".util.view_utils.app_bar.DragControlAppBarLayoutBehaviour"
app:layout_behavior=
".util.view_utils.app_bar.DragControlAppBarLayoutBehaviour"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:liftOnScroll=
"true"
tools:visibility=
"visible"
>
tools:visibility=
"visible"
>
<com.google.android.material.appbar.CollapsingToolbarLayout
<com.google.android.material.appbar.CollapsingToolbarLayout
...
@@ -47,9 +46,9 @@
...
@@ -47,9 +46,9 @@
android:layout_height=
"?android:attr/actionBarSize"
android:layout_height=
"?android:attr/actionBarSize"
android:visibility=
"invisible"
android:visibility=
"invisible"
app:layout_collapseMode=
"pin"
app:layout_collapseMode=
"pin"
app:titleTextAppearance=
"@style/Header_TextView.Main_Header"
app:popupTheme=
"@style/ThemeOverlay.AppCompat.Light"
app:popupTheme=
"@style/ThemeOverlay.AppCompat.Light"
app:showAsAction=
"always"
app:showAsAction=
"always"
app:titleTextAppearance=
"@style/Header_TextView.Main_Header"
tools:visibility=
"invisible"
>
tools:visibility=
"invisible"
>
</androidx.appcompat.widget.Toolbar>
</androidx.appcompat.widget.Toolbar>
...
@@ -62,7 +61,7 @@
...
@@ -62,7 +61,7 @@
android:id=
"@+id/conductor_container"
android:id=
"@+id/conductor_container"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
app:layout_behavior=
"com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
>
app:layout_behavior=
"com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
>
<include
<include
layout=
"@layout/test_progress_status"
layout=
"@layout/test_progress_status"
...
@@ -71,12 +70,12 @@
...
@@ -71,12 +70,12 @@
</FrameLayout>
</FrameLayout>
<!-- <com.bluelinelabs.conductor.ChangeHandlerFrameLayout-->
<!-- <com.bluelinelabs.conductor.ChangeHandlerFrameLayout-->
<!-- android:id="@+id/conductor_container"-->
<!-- android:id="@+id/conductor_container"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:background="@color/colorBackground"-->
<!-- android:background="@color/colorBackground"-->
<!-- app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />-->
<!-- app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />-->
<!--</android.support.constraint.ConstraintLayout>-->
<!--</android.support.constraint.ConstraintLayout>-->
...
...
app/src/main/res/layout/authentication_screen.xml
View file @
5d7e5a33
...
@@ -52,13 +52,16 @@
...
@@ -52,13 +52,16 @@
android:layout_marginStart=
"16dp"
android:layout_marginStart=
"16dp"
android:layout_marginTop=
"16dp"
android:layout_marginTop=
"16dp"
android:layout_marginEnd=
"16dp"
android:layout_marginEnd=
"16dp"
android:nextFocusDown=
"@id/password_text_input"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/textView3"
>
app:layout_constraintTop_toBottomOf=
"@+id/textView3"
>
<com.google.android.material.textfield.TextInputEditText
<com.google.android.material.textfield.TextInputEditText
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
android:layout_height=
"wrap_content"
android:inputType=
"textEmailAddress"
android:maxLines=
"1"
/>
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<FrameLayout
<FrameLayout
...
@@ -76,12 +79,16 @@
...
@@ -76,12 +79,16 @@
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:id=
"@+id/password_text_input"
android:id=
"@+id/password_text_input"
style=
"@style/AuthTextInputLayout.Password"
style=
"@style/AuthTextInputLayout.Password"
android:nextFocusDown=
"@id/sign_in_button"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
android:layout_height=
"match_parent"
>
<com.google.android.material.textfield.TextInputEditText
<com.google.android.material.textfield.TextInputEditText
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
android:layout_height=
"wrap_content"
android:inputType=
"textPassword"
android:maxLength=
"64"
android:maxLines=
"1"
/>
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
<LinearLayout
...
...
app/src/main/res/layout/settings_screen.xml
View file @
5d7e5a33
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
<androidx.core.widget.NestedScrollView
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/nestedScrollContainer"
android:id=
"@+id/nestedScrollContainer"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<LinearLayout
xmlns:tools=
"http://schemas.android.com/tools"
<LinearLayout
android:orientation=
"vertical"
android:orientation=
"vertical"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
android:layout_height=
"match_parent"
>
...
@@ -139,11 +139,11 @@
...
@@ -139,11 +139,11 @@
<com.google.android.material.textview.MaterialTextView
<com.google.android.material.textview.MaterialTextView
android:id=
"@+id/signOutButton"
style=
"@style/Default_TextView.Cancel_Text"
style=
"@style/Default_TextView.Cancel_Text"
android:text=
"СМЕНИТЬ АККАУНТ"
android:layout_margin=
"32dp"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
/>
android:layout_margin=
"32dp"
android:text=
"СМЕНИТЬ АККАУНТ"
/>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.core.widget.NestedScrollView>
\ No newline at end of file
app/src/main/res/values/styles.xml
View file @
5d7e5a33
...
@@ -41,6 +41,7 @@
...
@@ -41,6 +41,7 @@
<style
name=
"Auth.ErrorText"
parent=
"TextAppearance.Design.Error"
>
<style
name=
"Auth.ErrorText"
parent=
"TextAppearance.Design.Error"
>
<item
name=
"android:textColor"
>
@color/colorError
</item>
<item
name=
"android:textColor"
>
@color/colorError
</item>
<item
name=
"android:textSize"
>
@dimen/lite_notice
</item>
</style>
</style>
<style
name=
"Auth.EditText"
parent=
"Widget.AppCompat.EditText"
>
<style
name=
"Auth.EditText"
parent=
"Widget.AppCompat.EditText"
>
...
@@ -151,6 +152,7 @@
...
@@ -151,6 +152,7 @@
<style
name=
"AuthButton.Enable"
>
<style
name=
"AuthButton.Enable"
>
<item
name=
"android:text"
>
"ВОЙТИ"
</item>
<item
name=
"android:text"
>
"ВОЙТИ"
</item>
<item
name=
"android:textColor"
>
@color/sign_in_button_selector
</item>
<item
name=
"strokeColor"
>
@color/sign_in_button_selector
</item>
<item
name=
"strokeColor"
>
@color/sign_in_button_selector
</item>
</style>
</style>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment