Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
Administrator
AloqaIM-Android
Commits
36ff29d7
Unverified
Commit
36ff29d7
authored
Apr 16, 2018
by
Rafael Kellermann Streit
Committed by
GitHub
Apr 16, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1093 from RocketChat/new/auth-deep-link
[NEW] Auth deep link
parents
ee50029f
6091ee3d
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
230 additions
and
40 deletions
+230
-40
build.gradle
app/build.gradle
+4
-0
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+13
-0
LoginDeepLinkInfo.kt
.../android/authentication/domain/model/LoginDeepLinkInfo.kt
+38
-0
LoginPresenter.kt
...droid/authentication/login/presentation/LoginPresenter.kt
+48
-6
LoginFragment.kt
...t/rocket/android/authentication/login/ui/LoginFragment.kt
+16
-2
AuthenticationNavigator.kt
...id/authentication/presentation/AuthenticationNavigator.kt
+7
-0
ServerPresenter.kt
...oid/authentication/server/presentation/ServerPresenter.kt
+16
-6
ServerFragment.kt
...rocket/android/authentication/server/ui/ServerFragment.kt
+15
-1
TwoFAFragment.kt
...cket/android/authentication/twofactor/ui/TwoFAFragment.kt
+1
-1
AuthenticationActivity.kt
...ocket/android/authentication/ui/AuthenticationActivity.kt
+8
-5
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+2
-2
MessageView.kt
...n/java/chat/rocket/android/core/behaviours/MessageView.kt
+9
-0
MainPresenter.kt
...va/chat/rocket/android/main/presentation/MainPresenter.kt
+2
-2
RefreshSettingsInteractor.kt
...rocket/android/server/domain/RefreshSettingsInteractor.kt
+4
-1
CheckServerPresenter.kt
...ocket/android/server/presentation/CheckServerPresenter.kt
+47
-14
No files found.
app/build.gradle
View file @
36ff29d7
...
@@ -124,6 +124,10 @@ kotlin {
...
@@ -124,6 +124,10 @@ kotlin {
}
}
}
}
androidExtensions
{
experimental
=
true
}
// FIXME - build and install the sdk into the app/libs directory
// FIXME - build and install the sdk into the app/libs directory
// We were having some issues with the kapt generated files from the sdk when importing as a module
// We were having some issues with the kapt generated files from the sdk when importing as a module
task
compileSdk
(
type:
Exec
)
{
task
compileSdk
(
type:
Exec
)
{
...
...
app/src/main/AndroidManifest.xml
View file @
36ff29d7
...
@@ -35,6 +35,19 @@
...
@@ -35,6 +35,19 @@
<category
android:name=
"android.intent.category.DEFAULT"
/>
<category
android:name=
"android.intent.category.DEFAULT"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
<intent-filter>
<action
android:name=
"android.intent.action.VIEW"
/>
<category
android:name=
"android.intent.category.BROWSABLE"
/>
<category
android:name=
"android.intent.category.DEFAULT"
/>
<data
android:host=
"auth"
android:scheme=
"rocketchat"
/>
<data
android:host=
"go.rocket.chat"
android:path=
"/auth"
android:scheme=
"https"
/>
</intent-filter>
</intent-filter>
</activity>
</activity>
<activity
<activity
...
...
app/src/main/java/chat/rocket/android/authentication/domain/model/LoginDeepLinkInfo.kt
0 → 100644
View file @
36ff29d7
package
chat.rocket.android.authentication.domain.model
import
android.content.Intent
import
android.net.Uri
import
android.os.Parcelable
import
kotlinx.android.parcel.Parcelize
import
timber.log.Timber
@Parcelize
data class
LoginDeepLinkInfo
(
val
url
:
String
,
val
userId
:
String
,
val
token
:
String
)
:
Parcelable
fun
Intent
.
getLoginDeepLinkInfo
():
LoginDeepLinkInfo
?
{
val
uri
=
data
return
if
(
action
==
Intent
.
ACTION_VIEW
&&
uri
!=
null
&&
uri
.
isAuthenticationDeepLink
())
{
val
host
=
uri
.
getQueryParameter
(
"host"
)
val
url
=
if
(
host
.
startsWith
(
"http"
))
host
else
"https://$host"
val
userId
=
uri
.
getQueryParameter
(
"userId"
)
val
token
=
uri
.
getQueryParameter
(
"token"
)
try
{
LoginDeepLinkInfo
(
url
,
userId
,
token
)
}
catch
(
ex
:
Exception
)
{
Timber
.
d
(
ex
,
"Error parsing login deeplink"
)
null
}
}
else
null
}
private
inline
fun
Uri
.
isAuthenticationDeepLink
():
Boolean
{
if
(
host
==
"auth"
)
return
true
else
if
(
host
==
"go.rocket.chat"
&&
path
==
"/auth"
)
return
true
return
false
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginPresenter.kt
View file @
36ff29d7
package
chat.rocket.android.authentication.login.presentation
package
chat.rocket.android.authentication.login.presentation
import
chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import
chat.rocket.android.authentication.presentation.AuthenticationNavigator
import
chat.rocket.android.authentication.presentation.AuthenticationNavigator
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.helper.OauthHelper
import
chat.rocket.android.helper.OauthHelper
...
@@ -10,6 +11,7 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory
...
@@ -10,6 +11,7 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.presentation.CheckServerPresenter
import
chat.rocket.android.server.presentation.CheckServerPresenter
import
chat.rocket.android.util.extensions.*
import
chat.rocket.android.util.extensions.*
import
chat.rocket.android.util.retryIO
import
chat.rocket.android.util.retryIO
import
chat.rocket.common.RocketChatAuthException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatTwoFactorException
import
chat.rocket.common.RocketChatTwoFactorException
import
chat.rocket.common.model.Token
import
chat.rocket.common.model.Token
...
@@ -24,6 +26,7 @@ import javax.inject.Inject
...
@@ -24,6 +26,7 @@ import javax.inject.Inject
private
const
val
TYPE_LOGIN_USER_EMAIL
=
0
private
const
val
TYPE_LOGIN_USER_EMAIL
=
0
private
const
val
TYPE_LOGIN_CAS
=
1
private
const
val
TYPE_LOGIN_CAS
=
1
private
const
val
TYPE_LOGIN_OAUTH
=
2
private
const
val
TYPE_LOGIN_OAUTH
=
2
private
const
val
TYPE_LOGIN_DEEP_LINK
=
3
private
const
val
SERVICE_NAME_GITHUB
=
"github"
private
const
val
SERVICE_NAME_GITHUB
=
"github"
private
const
val
SERVICE_NAME_GOOGLE
=
"google"
private
const
val
SERVICE_NAME_GOOGLE
=
"google"
private
const
val
SERVICE_NAME_LINKEDIN
=
"linkedin"
private
const
val
SERVICE_NAME_LINKEDIN
=
"linkedin"
...
@@ -35,26 +38,31 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
...
@@ -35,26 +38,31 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
private
val
tokenRepository
:
TokenRepository
,
private
val
tokenRepository
:
TokenRepository
,
private
val
localRepository
:
LocalRepository
,
private
val
localRepository
:
LocalRepository
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
settingsInteractor
:
GetSettingsInteractor
,
private
val
settingsInteractor
:
GetSettingsInteractor
,
serverInteractor
:
GetCurrentServerInteractor
,
serverInteractor
:
GetCurrentServerInteractor
,
private
val
saveAccountInteractor
:
SaveAccountInteractor
,
private
val
saveAccountInteractor
:
SaveAccountInteractor
,
private
val
factory
:
RocketChatClientFactory
)
private
val
factory
:
RocketChatClientFactory
)
:
CheckServerPresenter
(
strategy
,
factory
.
create
(
serverInteractor
.
get
()
!!
)
,
view
)
{
:
CheckServerPresenter
(
strategy
,
factory
,
view
)
{
// TODO - we should validate the current server when opening the app, and have a nonnull get()
// TODO - we should validate the current server when opening the app, and have a nonnull get()
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
client
:
RocketChatClient
=
factory
.
create
(
currentServer
)
private
lateinit
var
client
:
RocketChatClient
private
val
settings
:
PublicSettings
=
settingsInteractor
.
get
(
currentServer
)
private
lateinit
var
settings
:
PublicSettings
//private val client: RocketChatClient = factory.create(currentServer)
//private val settings: PublicSettings = settingsInteractor.get(currentServer)
private
lateinit
var
usernameOrEmail
:
String
private
lateinit
var
usernameOrEmail
:
String
private
lateinit
var
password
:
String
private
lateinit
var
password
:
String
private
lateinit
var
credentialToken
:
String
private
lateinit
var
credentialToken
:
String
private
lateinit
var
credentialSecret
:
String
private
lateinit
var
credentialSecret
:
String
private
lateinit
var
deepLinkUserId
:
String
private
lateinit
var
deepLinkToken
:
String
fun
setupView
()
{
fun
setupView
()
{
setupConnectionInfo
(
currentServer
)
setupLoginView
()
setupLoginView
()
setupUserRegistrationView
()
setupUserRegistrationView
()
setupCasView
()
setupCasView
()
setupOauthServicesView
()
setupOauthServicesView
()
checkServerInfo
()
checkServerInfo
(
currentServer
)
}
}
fun
authenticateWithUserAndPassword
(
usernameOrEmail
:
String
,
password
:
String
)
{
fun
authenticateWithUserAndPassword
(
usernameOrEmail
:
String
,
password
:
String
)
{
...
@@ -84,6 +92,32 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
...
@@ -84,6 +92,32 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
doAuthentication
(
TYPE_LOGIN_OAUTH
)
doAuthentication
(
TYPE_LOGIN_OAUTH
)
}
}
fun
authenticadeWithDeepLink
(
deepLinkInfo
:
LoginDeepLinkInfo
)
{
val
serverUrl
=
deepLinkInfo
.
url
setupConnectionInfo
(
serverUrl
)
deepLinkUserId
=
deepLinkInfo
.
userId
deepLinkToken
=
deepLinkInfo
.
token
tokenRepository
.
save
(
serverUrl
,
Token
(
deepLinkUserId
,
deepLinkToken
))
launchUI
(
strategy
)
{
try
{
val
version
=
checkServerVersion
(
serverUrl
).
await
()
when
(
version
)
{
is
Version
.
OutOfDateError
->
{
view
.
blockAndAlertNotRequiredVersion
()
}
else
->
doAuthentication
(
TYPE_LOGIN_DEEP_LINK
)
}
}
catch
(
ex
:
Exception
)
{
Timber
.
d
(
ex
,
"Error performing deep link login"
)
}
}
}
private
fun
setupConnectionInfo
(
serverUrl
:
String
)
{
client
=
factory
.
create
(
serverUrl
)
settings
=
settingsInteractor
.
get
(
serverUrl
)
}
fun
signup
()
=
navigator
.
toSignUp
()
fun
signup
()
=
navigator
.
toSignUp
()
private
fun
setupLoginView
()
{
private
fun
setupLoginView
()
{
...
@@ -212,8 +246,16 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
...
@@ -212,8 +246,16 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
TYPE_LOGIN_OAUTH
->
{
TYPE_LOGIN_OAUTH
->
{
client
.
loginWithOauth
(
credentialToken
,
credentialSecret
)
client
.
loginWithOauth
(
credentialToken
,
credentialSecret
)
}
}
TYPE_LOGIN_DEEP_LINK
->
{
val
myself
=
client
.
me
()
// Just checking if the credentials worked.
if
(
myself
.
id
==
deepLinkUserId
)
{
Token
(
deepLinkUserId
,
deepLinkToken
)
}
else
{
throw
RocketChatAuthException
(
"Invalid Authentication Deep Link Credentials..."
)
}
}
else
->
{
else
->
{
throw
IllegalStateException
(
"Expected TYPE_LOGIN_USER_EMAIL, TYPE_LOGIN_CAS
or TYPE_LOGIN_OAUTH
"
)
throw
IllegalStateException
(
"Expected TYPE_LOGIN_USER_EMAIL, TYPE_LOGIN_CAS
, TYPE_LOGIN_OAUTH or TYPE_LOGIN_DEEP_LINK
"
)
}
}
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/authentication/login/ui/LoginFragment.kt
View file @
36ff29d7
...
@@ -17,6 +17,7 @@ import android.widget.ScrollView
...
@@ -17,6 +17,7 @@ import android.widget.ScrollView
import
androidx.core.view.postDelayed
import
androidx.core.view.postDelayed
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import
chat.rocket.android.authentication.login.presentation.LoginPresenter
import
chat.rocket.android.authentication.login.presentation.LoginPresenter
import
chat.rocket.android.authentication.login.presentation.LoginView
import
chat.rocket.android.authentication.login.presentation.LoginView
import
chat.rocket.android.helper.KeyboardHelper
import
chat.rocket.android.helper.KeyboardHelper
...
@@ -27,6 +28,7 @@ import chat.rocket.android.webview.cas.ui.casWebViewIntent
...
@@ -27,6 +28,7 @@ import chat.rocket.android.webview.cas.ui.casWebViewIntent
import
chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET
import
chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET
import
chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN
import
chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN
import
chat.rocket.android.webview.oauth.ui.oauthWebViewIntent
import
chat.rocket.android.webview.oauth.ui.oauthWebViewIntent
import
chat.rocket.common.util.ifNull
import
dagger.android.support.AndroidSupportInjection
import
dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_authentication_log_in.*
import
kotlinx.android.synthetic.main.fragment_authentication_log_in.*
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -41,14 +43,22 @@ class LoginFragment : Fragment(), LoginView {
...
@@ -41,14 +43,22 @@ class LoginFragment : Fragment(), LoginView {
areLoginOptionsNeeded
()
areLoginOptionsNeeded
()
}
}
private
var
isGlobalLayoutListenerSetUp
=
false
private
var
isGlobalLayoutListenerSetUp
=
false
private
var
deepLinkInfo
:
LoginDeepLinkInfo
?
=
null
companion
object
{
companion
object
{
fun
newInstance
()
=
LoginFragment
()
private
const
val
DEEP_LINK_INFO
=
"DeepLinkInfo"
fun
newInstance
(
deepLinkInfo
:
LoginDeepLinkInfo
?
=
null
)
=
LoginFragment
().
apply
{
arguments
=
Bundle
().
apply
{
putParcelable
(
DEEP_LINK_INFO
,
deepLinkInfo
)
}
}
}
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
AndroidSupportInjection
.
inject
(
this
)
AndroidSupportInjection
.
inject
(
this
)
deepLinkInfo
=
arguments
?.
getParcelable
(
DEEP_LINK_INFO
)
}
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
=
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
=
...
@@ -61,7 +71,11 @@ class LoginFragment : Fragment(), LoginView {
...
@@ -61,7 +71,11 @@ class LoginFragment : Fragment(), LoginView {
tintEditTextDrawableStart
()
tintEditTextDrawableStart
()
}
}
presenter
.
setupView
()
deepLinkInfo
?.
let
{
presenter
.
authenticadeWithDeepLink
(
it
)
}.
ifNull
{
presenter
.
setupView
()
}
}
}
override
fun
onDestroyView
()
{
override
fun
onDestroyView
()
{
...
...
app/src/main/java/chat/rocket/android/authentication/presentation/AuthenticationNavigator.kt
View file @
36ff29d7
...
@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.presentation
...
@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.presentation
import
android.content.Intent
import
android.content.Intent
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import
chat.rocket.android.authentication.login.ui.LoginFragment
import
chat.rocket.android.authentication.login.ui.LoginFragment
import
chat.rocket.android.authentication.registerusername.ui.RegisterUsernameFragment
import
chat.rocket.android.authentication.registerusername.ui.RegisterUsernameFragment
import
chat.rocket.android.authentication.signup.ui.SignupFragment
import
chat.rocket.android.authentication.signup.ui.SignupFragment
...
@@ -21,6 +22,12 @@ class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
...
@@ -21,6 +22,12 @@ class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
}
}
}
}
fun
toLogin
(
deepLinkInfo
:
LoginDeepLinkInfo
)
{
activity
.
addFragmentBackStack
(
"LoginFragment"
,
R
.
id
.
fragment_container
)
{
LoginFragment
.
newInstance
(
deepLinkInfo
)
}
}
fun
toTwoFA
(
username
:
String
,
password
:
String
)
{
fun
toTwoFA
(
username
:
String
,
password
:
String
)
{
activity
.
addFragmentBackStack
(
"TwoFAFragment"
,
R
.
id
.
fragment_container
)
{
activity
.
addFragmentBackStack
(
"TwoFAFragment"
,
R
.
id
.
fragment_container
)
{
TwoFAFragment
.
newInstance
(
username
,
password
)
TwoFAFragment
.
newInstance
(
username
,
password
)
...
...
app/src/main/java/chat/rocket/android/authentication/server/presentation/ServerPresenter.kt
View file @
36ff29d7
package
chat.rocket.android.authentication.server.presentation
package
chat.rocket.android.authentication.server.presentation
import
chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import
chat.rocket.android.authentication.presentation.AuthenticationNavigator
import
chat.rocket.android.authentication.presentation.AuthenticationNavigator
import
chat.rocket.android.core.behaviours.showMessage
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.server.domain.GetAccountsInteractor
import
chat.rocket.android.server.domain.GetAccountsInteractor
import
chat.rocket.android.server.domain.RefreshSettingsInteractor
import
chat.rocket.android.server.domain.RefreshSettingsInteractor
...
@@ -18,6 +20,12 @@ class ServerPresenter @Inject constructor(private val view: ServerView,
...
@@ -18,6 +20,12 @@ class ServerPresenter @Inject constructor(private val view: ServerView,
private
val
getAccountsInteractor
:
GetAccountsInteractor
)
{
private
val
getAccountsInteractor
:
GetAccountsInteractor
)
{
fun
connect
(
server
:
String
)
{
fun
connect
(
server
:
String
)
{
connectToServer
(
server
)
{
navigator
.
toLogin
()
}
}
fun
connectToServer
(
server
:
String
,
block
:
()
->
Unit
)
{
if
(!
server
.
isValidUrl
())
{
if
(!
server
.
isValidUrl
())
{
view
.
showInvalidServerUrlMessage
()
view
.
showInvalidServerUrlMessage
()
}
else
{
}
else
{
...
@@ -33,17 +41,19 @@ class ServerPresenter @Inject constructor(private val view: ServerView,
...
@@ -33,17 +41,19 @@ class ServerPresenter @Inject constructor(private val view: ServerView,
try
{
try
{
refreshSettingsInteractor
.
refresh
(
server
)
refreshSettingsInteractor
.
refresh
(
server
)
serverInteractor
.
save
(
server
)
serverInteractor
.
save
(
server
)
navigator
.
toLogin
()
block
()
}
catch
(
ex
:
Exception
)
{
}
catch
(
ex
:
Exception
)
{
ex
.
message
?.
let
{
view
.
showMessage
(
ex
)
view
.
showMessage
(
it
)
}.
ifNull
{
view
.
showGenericErrorMessage
()
}
}
finally
{
}
finally
{
view
.
hideLoading
()
view
.
hideLoading
()
}
}
}
}
}
}
}
}
fun
deepLink
(
deepLinkInfo
:
LoginDeepLinkInfo
)
{
connectToServer
(
deepLinkInfo
.
url
)
{
navigator
.
toLogin
(
deepLinkInfo
)
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/authentication/server/ui/ServerFragment.kt
View file @
36ff29d7
...
@@ -7,6 +7,7 @@ import android.view.View
...
@@ -7,6 +7,7 @@ import android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
import
android.view.ViewTreeObserver
import
android.view.ViewTreeObserver
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import
chat.rocket.android.authentication.server.presentation.ServerPresenter
import
chat.rocket.android.authentication.server.presentation.ServerPresenter
import
chat.rocket.android.authentication.server.presentation.ServerView
import
chat.rocket.android.authentication.server.presentation.ServerView
import
chat.rocket.android.helper.KeyboardHelper
import
chat.rocket.android.helper.KeyboardHelper
...
@@ -17,17 +18,26 @@ import javax.inject.Inject
...
@@ -17,17 +18,26 @@ import javax.inject.Inject
class
ServerFragment
:
Fragment
(),
ServerView
{
class
ServerFragment
:
Fragment
(),
ServerView
{
@Inject
lateinit
var
presenter
:
ServerPresenter
@Inject
lateinit
var
presenter
:
ServerPresenter
private
var
deepLinkInfo
:
LoginDeepLinkInfo
?
=
null
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
text_server_url
.
isCursorVisible
=
KeyboardHelper
.
isSoftKeyboardShown
(
relative_layout
.
rootView
)
text_server_url
.
isCursorVisible
=
KeyboardHelper
.
isSoftKeyboardShown
(
relative_layout
.
rootView
)
}
}
companion
object
{
companion
object
{
fun
newInstance
()
=
ServerFragment
()
private
const
val
DEEP_LINK_INFO
=
"DeepLinkInfo"
fun
newInstance
(
deepLinkInfo
:
LoginDeepLinkInfo
?)
=
ServerFragment
().
apply
{
arguments
=
Bundle
().
apply
{
putParcelable
(
DEEP_LINK_INFO
,
deepLinkInfo
)
}
}
}
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
AndroidSupportInjection
.
inject
(
this
)
AndroidSupportInjection
.
inject
(
this
)
deepLinkInfo
=
arguments
?.
getParcelable
(
DEEP_LINK_INFO
)
}
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
=
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
=
...
@@ -37,6 +47,10 @@ class ServerFragment : Fragment(), ServerView {
...
@@ -37,6 +47,10 @@ class ServerFragment : Fragment(), ServerView {
super
.
onViewCreated
(
view
,
savedInstanceState
)
super
.
onViewCreated
(
view
,
savedInstanceState
)
relative_layout
.
viewTreeObserver
.
addOnGlobalLayoutListener
(
layoutListener
)
relative_layout
.
viewTreeObserver
.
addOnGlobalLayoutListener
(
layoutListener
)
setupOnClickListener
()
setupOnClickListener
()
deepLinkInfo
?.
let
{
presenter
.
deepLink
(
it
)
}
}
}
override
fun
onDestroyView
()
{
override
fun
onDestroyView
()
{
...
...
app/src/main/java/chat/rocket/android/authentication/twofactor/ui/TwoFAFragment.kt
View file @
36ff29d7
...
@@ -28,7 +28,7 @@ class TwoFAFragment : Fragment(), TwoFAView {
...
@@ -28,7 +28,7 @@ class TwoFAFragment : Fragment(), TwoFAView {
private
const
val
PASSWORD
=
"password"
private
const
val
PASSWORD
=
"password"
fun
newInstance
(
username
:
String
,
password
:
String
)
=
TwoFAFragment
().
apply
{
fun
newInstance
(
username
:
String
,
password
:
String
)
=
TwoFAFragment
().
apply
{
arguments
=
Bundle
(
1
).
apply
{
arguments
=
Bundle
(
2
).
apply
{
putString
(
USERNAME
,
username
)
putString
(
USERNAME
,
username
)
putString
(
PASSWORD
,
password
)
putString
(
PASSWORD
,
password
)
}
}
...
...
app/src/main/java/chat/rocket/android/authentication/ui/AuthenticationActivity.kt
View file @
36ff29d7
...
@@ -6,10 +6,11 @@ import android.os.Bundle
...
@@ -6,10 +6,11 @@ import android.os.Bundle
import
android.support.v4.app.Fragment
import
android.support.v4.app.Fragment
import
android.support.v7.app.AppCompatActivity
import
android.support.v7.app.AppCompatActivity
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import
chat.rocket.android.authentication.domain.model.getLoginDeepLinkInfo
import
chat.rocket.android.authentication.presentation.AuthenticationPresenter
import
chat.rocket.android.authentication.presentation.AuthenticationPresenter
import
chat.rocket.android.authentication.server.ui.ServerFragment
import
chat.rocket.android.authentication.server.ui.ServerFragment
import
chat.rocket.android.util.extensions.addFragment
import
chat.rocket.android.util.extensions.addFragment
import
chat.rocket.android.util.extensions.launchUI
import
dagger.android.AndroidInjection
import
dagger.android.AndroidInjection
import
dagger.android.AndroidInjector
import
dagger.android.AndroidInjector
import
dagger.android.DispatchingAndroidInjector
import
dagger.android.DispatchingAndroidInjector
...
@@ -30,11 +31,13 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
...
@@ -30,11 +31,13 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
setTheme
(
R
.
style
.
AuthenticationTheme
)
setTheme
(
R
.
style
.
AuthenticationTheme
)
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
val
deepLinkInfo
=
intent
.
getLoginDeepLinkInfo
()
launch
(
UI
+
job
)
{
launch
(
UI
+
job
)
{
val
newServer
=
intent
.
getBooleanExtra
(
INTENT_ADD_NEW_SERVER
,
false
)
val
newServer
=
intent
.
getBooleanExtra
(
INTENT_ADD_NEW_SERVER
,
false
)
presenter
.
loadCredentials
(
newServer
)
{
authenticated
->
// if we got authenticadeWithDeepLink information, pass true to newServer also
presenter
.
loadCredentials
(
newServer
||
deepLinkInfo
!=
null
)
{
authenticated
->
if
(!
authenticated
)
{
if
(!
authenticated
)
{
showServerInput
(
savedInstanceState
)
showServerInput
(
savedInstanceState
,
deepLinkInfo
)
}
}
}
}
}
}
...
@@ -49,9 +52,9 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
...
@@ -49,9 +52,9 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
return
fragmentDispatchingAndroidInjector
return
fragmentDispatchingAndroidInjector
}
}
fun
showServerInput
(
savedInstanceState
:
Bundle
?)
{
fun
showServerInput
(
savedInstanceState
:
Bundle
?
,
deepLinkInfo
:
LoginDeepLinkInfo
?
)
{
addFragment
(
"ServerFragment"
,
R
.
id
.
fragment_container
)
{
addFragment
(
"ServerFragment"
,
R
.
id
.
fragment_container
)
{
ServerFragment
.
newInstance
()
ServerFragment
.
newInstance
(
deepLinkInfo
)
}
}
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
36ff29d7
...
@@ -233,9 +233,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -233,9 +233,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
// if y is positive the keyboard is up else it's down
// if y is positive the keyboard is up else it's down
recycler_view
.
post
{
recycler_view
.
post
{
if
(
y
>
0
||
Math
.
abs
(
verticalScrollOffset
.
get
())
>=
Math
.
abs
(
y
))
{
if
(
y
>
0
||
Math
.
abs
(
verticalScrollOffset
.
get
())
>=
Math
.
abs
(
y
))
{
recycler_view
.
scrollBy
(
0
,
y
)
ui
{
recycler_view
.
scrollBy
(
0
,
y
)
}
}
else
{
}
else
{
recycler_view
.
scrollBy
(
0
,
verticalScrollOffset
.
get
())
ui
{
recycler_view
.
scrollBy
(
0
,
verticalScrollOffset
.
get
())
}
}
}
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/core/behaviours/MessageView.kt
View file @
36ff29d7
package
chat.rocket.android.core.behaviours
package
chat.rocket.android.core.behaviours
import
android.support.annotation.StringRes
import
android.support.annotation.StringRes
import
chat.rocket.common.util.ifNull
interface
MessageView
{
interface
MessageView
{
...
@@ -14,4 +15,12 @@ interface MessageView {
...
@@ -14,4 +15,12 @@ interface MessageView {
fun
showMessage
(
message
:
String
)
fun
showMessage
(
message
:
String
)
fun
showGenericErrorMessage
()
fun
showGenericErrorMessage
()
}
fun
MessageView
.
showMessage
(
ex
:
Exception
)
{
ex
.
message
?.
let
{
showMessage
(
it
)
}.
ifNull
{
showGenericErrorMessage
()
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/main/presentation/MainPresenter.kt
View file @
36ff29d7
...
@@ -41,7 +41,7 @@ class MainPresenter @Inject constructor(
...
@@ -41,7 +41,7 @@ class MainPresenter @Inject constructor(
private
val
factory
:
RocketChatClientFactory
,
private
val
factory
:
RocketChatClientFactory
,
getSettingsInteractor
:
GetSettingsInteractor
,
getSettingsInteractor
:
GetSettingsInteractor
,
managerFactory
:
ConnectionManagerFactory
managerFactory
:
ConnectionManagerFactory
)
:
CheckServerPresenter
(
strategy
,
client
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
,
view
=
view
)
{
)
:
CheckServerPresenter
(
strategy
,
factory
,
view
=
view
)
{
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
manager
=
managerFactory
.
create
(
currentServer
)
private
val
manager
=
managerFactory
.
create
(
currentServer
)
private
val
client
:
RocketChatClient
=
factory
.
create
(
currentServer
)
private
val
client
:
RocketChatClient
=
factory
.
create
(
currentServer
)
...
@@ -56,7 +56,7 @@ class MainPresenter @Inject constructor(
...
@@ -56,7 +56,7 @@ class MainPresenter @Inject constructor(
fun
toSettings
()
=
navigator
.
toSettings
()
fun
toSettings
()
=
navigator
.
toSettings
()
fun
loadCurrentInfo
()
{
fun
loadCurrentInfo
()
{
checkServerInfo
()
checkServerInfo
(
currentServer
)
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
try
{
try
{
val
me
=
retryIO
(
"me"
)
{
val
me
=
retryIO
(
"me"
)
{
...
...
app/src/main/java/chat/rocket/android/server/domain/RefreshSettingsInteractor.kt
View file @
36ff29d7
package
chat.rocket.android.server.domain
package
chat.rocket.android.server.domain
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.retryIO
import
chat.rocket.core.internal.rest.settings
import
chat.rocket.core.internal.rest.settings
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.async
import
kotlinx.coroutines.experimental.async
...
@@ -27,7 +28,9 @@ class RefreshSettingsInteractor @Inject constructor(private val factory: RocketC
...
@@ -27,7 +28,9 @@ class RefreshSettingsInteractor @Inject constructor(private val factory: RocketC
suspend
fun
refresh
(
server
:
String
)
{
suspend
fun
refresh
(
server
:
String
)
{
withContext
(
CommonPool
)
{
withContext
(
CommonPool
)
{
factory
.
create
(
server
).
let
{
client
->
factory
.
create
(
server
).
let
{
client
->
val
settings
=
client
.
settings
(*
settingsFilter
)
val
settings
=
retryIO
(
description
=
"settings"
,
times
=
5
)
{
client
.
settings
(*
settingsFilter
)
}
repository
.
save
(
server
,
settings
)
repository
.
save
(
server
,
settings
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/server/presentation/CheckServerPresenter.kt
View file @
36ff29d7
...
@@ -3,33 +3,40 @@ package chat.rocket.android.server.presentation
...
@@ -3,33 +3,40 @@ package chat.rocket.android.server.presentation
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.authentication.server.presentation.VersionCheckView
import
chat.rocket.android.authentication.server.presentation.VersionCheckView
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.VersionInfo
import
chat.rocket.android.util.VersionInfo
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.android.util.retryIO
import
chat.rocket.android.util.retryIO
import
chat.rocket.core.RocketChatClient
import
chat.rocket.core.RocketChatClient
import
chat.rocket.core.internal.rest.serverInfo
import
chat.rocket.core.internal.rest.serverInfo
import
kotlinx.coroutines.experimental.Deferred
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.experimental.async
import
timber.log.Timber
import
timber.log.Timber
abstract
class
CheckServerPresenter
constructor
(
private
val
strategy
:
CancelStrategy
,
abstract
class
CheckServerPresenter
constructor
(
private
val
strategy
:
CancelStrategy
,
private
val
client
:
RocketChatClient
,
private
val
factory
:
RocketChatClientFactory
,
private
val
view
:
VersionCheckView
)
{
private
val
view
:
VersionCheckView
)
{
internal
fun
checkServerInfo
()
{
private
lateinit
var
currentServer
:
String
launchUI
(
strategy
)
{
private
val
client
:
RocketChatClient
by
lazy
{
factory
.
create
(
currentServer
)
}
internal
fun
checkServerInfo
(
serverUrl
:
String
):
Job
{
return
launchUI
(
strategy
)
{
try
{
try
{
val
serverInfo
=
retryIO
(
description
=
"serverInfo"
,
times
=
5
)
{
client
.
serverInfo
()
}
val
version
=
checkServerVersion
(
serverUrl
).
await
()
val
thisServerVersion
=
serverInfo
.
version
when
(
version
)
{
val
isRequiredVersion
=
isRequiredServerVersion
(
thisServerVersion
)
is
Version
.
VersionOk
->
{
val
isRecommendedVersion
=
isRecommendedServerVersion
(
thisServerVersion
)
Timber
.
i
(
"Your version is nice! (Requires: 0.62.0, Yours: ${version.version})"
)
if
(
isRequiredVersion
)
{
}
if
(
isRecommendedVersion
)
{
is
Version
.
RecommendedVersionWarning
->
{
Timber
.
i
(
"Your version is nice! (Requires: 0.62.0, Yours: $thisServerVersion)"
)
Timber
.
i
(
"Your server ${version.version} is bellow recommended version ${BuildConfig.RECOMMENDED_SERVER_VERSION}"
)
}
else
{
view
.
alertNotRecommendedVersion
()
view
.
alertNotRecommendedVersion
()
}
}
}
else
{
is
Version
.
OutOfDateError
->
{
if
(!
isRecommendedVersion
)
{
Timber
.
i
(
"Oops. Looks like your server ${version.version} is out-of-date! Minimum server version required ${BuildConfig.REQUIRED_SERVER_VERSION}!"
)
view
.
blockAndAlertNotRequiredVersion
()
view
.
blockAndAlertNotRequiredVersion
()
Timber
.
i
(
"Oops. Looks like your server is out-of-date! Minimum server version required ${BuildConfig.REQUIRED_SERVER_VERSION}!"
)
}
}
}
}
}
catch
(
ex
:
Exception
)
{
}
catch
(
ex
:
Exception
)
{
...
@@ -38,6 +45,26 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
...
@@ -38,6 +45,26 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
}
}
}
}
internal
fun
checkServerVersion
(
serverUrl
:
String
):
Deferred
<
Version
>
{
currentServer
=
serverUrl
return
async
{
val
serverInfo
=
retryIO
(
description
=
"serverInfo"
,
times
=
5
)
{
client
.
serverInfo
()
}
val
thisServerVersion
=
serverInfo
.
version
val
isRequiredVersion
=
isRequiredServerVersion
(
thisServerVersion
)
val
isRecommendedVersion
=
isRecommendedServerVersion
(
thisServerVersion
)
if
(
isRequiredVersion
)
{
if
(
isRecommendedVersion
)
{
Timber
.
i
(
"Your version is nice! (Requires: 0.62.0, Yours: $thisServerVersion)"
)
return
@async
Version
.
VersionOk
(
thisServerVersion
)
}
else
{
return
@async
Version
.
RecommendedVersionWarning
(
thisServerVersion
)
}
}
else
{
return
@async
Version
.
OutOfDateError
(
thisServerVersion
)
}
}
}
private
fun
isRequiredServerVersion
(
version
:
String
):
Boolean
{
private
fun
isRequiredServerVersion
(
version
:
String
):
Boolean
{
return
isMinimumVersion
(
version
,
getVersionDistilled
(
BuildConfig
.
REQUIRED_SERVER_VERSION
))
return
isMinimumVersion
(
version
,
getVersionDistilled
(
BuildConfig
.
REQUIRED_SERVER_VERSION
))
}
}
...
@@ -92,4 +119,10 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
...
@@ -92,4 +119,10 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
0
0
}
}
}
}
sealed
class
Version
(
val
version
:
String
)
{
data class
VersionOk
(
private
val
currentVersion
:
String
)
:
Version
(
currentVersion
)
data class
RecommendedVersionWarning
(
private
val
currentVersion
:
String
)
:
Version
(
currentVersion
)
data class
OutOfDateError
(
private
val
currentVersion
:
String
)
:
Version
(
currentVersion
)
}
}
}
\ No newline at end of file
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