Unverified Commit ea6c8083 authored by Rafael Kellermann Streit's avatar Rafael Kellermann Streit Committed by GitHub

Merge pull request #1742 from RocketChat/beta

[RELEASE] Merge Beta to Master - Don't merge yet
parents 20ce8107 65de72ff
......@@ -16,8 +16,8 @@ android {
applicationId "chat.rocket.android"
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
versionCode 2043
versionName "2.6.1"
versionCode 2048
versionName "3.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
......@@ -93,6 +93,7 @@ dependencies {
implementation project(':draw')
implementation project(':util')
implementation project(':core')
implementation project(':suggestions')
implementation libraries.kotlin
implementation libraries.coroutines
......@@ -151,6 +152,8 @@ dependencies {
implementation libraries.livedataKtx
implementation 'com.google.code.findbugs:jsr305:3.0.2'
// Proprietary libraries
playImplementation libraries.fcm
playImplementation libraries.firebaseAnalytics
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
673693445664
673693445664
package chat.rocket.android.analytics
import chat.rocket.android.analytics.event.AuthenticationEvent
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.analytics.event.SubscriptionTypeEvent
class AnswersAnalytics : Analytics {
override fun logLogin(event: AuthenticationEvent, loginSucceeded: Boolean) {
// Do absolutely nothing
}
override fun logSignUp(event: AuthenticationEvent, signUpSucceeded: Boolean) {
// Do absolutely nothing
}
override fun logScreenView(event: ScreenViewEvent) {
// Do absolutely nothing
}
override fun logMessageSent(event: SubscriptionTypeEvent, serverUrl: String) {
// Do absolutely nothing
}
override fun logMediaUploaded(event: SubscriptionTypeEvent, mimeType: String) {
// Do absolutely nothing
}
override fun logReaction(event: SubscriptionTypeEvent) {
// Do absolutely nothing
}
override fun logServerSwitch(serverUrl: String, serverCount: Int) {
// Do absolutely nothing
}
}
class AnswersAnalytics : Analytics
\ No newline at end of file
package chat.rocket.android.analytics
import android.content.Context
import chat.rocket.android.analytics.event.AuthenticationEvent
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.analytics.event.SubscriptionTypeEvent
import javax.inject.Inject
class GoogleAnalyticsForFirebase @Inject constructor(val context: Context) :
Analytics {
override fun logLogin(event: AuthenticationEvent, loginSucceeded: Boolean) {
// Do absolutely nothing
}
override fun logSignUp(event: AuthenticationEvent, signUpSucceeded: Boolean) {
// Do absolutely nothing
}
override fun logScreenView(event: ScreenViewEvent) {
// Do absolutely nothing
}
override fun logMessageSent(event: SubscriptionTypeEvent, serverUrl: String) {
// Do absolutely nothing
}
override fun logMediaUploaded(event: SubscriptionTypeEvent, mimeType: String) {
// Do absolutely nothing
}
override fun logReaction(event: SubscriptionTypeEvent) {
// Do absolutely nothing
}
override fun logServerSwitch(serverUrl: String, serverCount: Int) {
// Do absolutely nothing
}
}
class GoogleAnalyticsForFirebase @Inject constructor(val context: Context) : Analytics
\ No newline at end of file
......@@ -9,24 +9,25 @@
<application
android:name=".app.RocketChatApplication"
tools:replace="android:name"
android:allowBackup="true"
android:fullBackupContent="@xml/backup_config"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true">
android:supportsRtl="true"
tools:replace="android:name">
<activity
android:name=".authentication.ui.AuthenticationActivity"
android:configChanges="orientation"
android:screenOrientation="portrait"
android:theme="@style/AuthenticationTheme"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
......@@ -40,6 +41,7 @@
<data
android:host="auth"
android:scheme="rocketchat" />
<data
android:host="go.rocket.chat"
android:path="/auth"
......@@ -49,7 +51,7 @@
<activity
android:name=".server.ui.ChangeServerActivity"
android:theme="@style/AuthenticationTheme" />
android:theme="@style/AppTheme" />
<activity
android:name=".main.ui.MainActivity"
......
......@@ -12,7 +12,7 @@ interface Analytics {
* @param event The [AuthenticationEvent] used to log in.
* @param loginSucceeded True if successful logged in, false otherwise.
*/
fun logLogin(event: AuthenticationEvent, loginSucceeded: Boolean)
fun logLogin(event: AuthenticationEvent, loginSucceeded: Boolean) {}
/**
* Logs the sign up event.
......@@ -20,14 +20,14 @@ interface Analytics {
* @param event The [AuthenticationEvent] used to sign up.
* @param signUpSucceeded True if successful signed up, false otherwise.
*/
fun logSignUp(event: AuthenticationEvent, signUpSucceeded: Boolean)
fun logSignUp(event: AuthenticationEvent, signUpSucceeded: Boolean) {}
/**
* Logs the screen view event.
*
* @param event The [ScreenViewEvent] to log.
*/
fun logScreenView(event: ScreenViewEvent)
fun logScreenView(event: ScreenViewEvent) {}
/**
* Logs the message sent event.
......@@ -35,7 +35,7 @@ interface Analytics {
* @param event The [SubscriptionTypeEvent] to log.
* @param serverUrl The server URL to log.
*/
fun logMessageSent(event: SubscriptionTypeEvent, serverUrl: String)
fun logMessageSent(event: SubscriptionTypeEvent, serverUrl: String) {}
/**
* Logs the media upload event.
......@@ -43,14 +43,14 @@ interface Analytics {
* @param event The [SubscriptionTypeEvent] to log.
* @param mimeType The mime type of the media uploaded to log.
*/
fun logMediaUploaded(event: SubscriptionTypeEvent, mimeType: String)
fun logMediaUploaded(event: SubscriptionTypeEvent, mimeType: String) {}
/**
* Logs the reaction event.
*
* @param event The [SubscriptionTypeEvent] to log.
*/
fun logReaction(event: SubscriptionTypeEvent)
fun logReaction(event: SubscriptionTypeEvent) {}
/**
* Logs the server switch event.
......@@ -58,5 +58,10 @@ interface Analytics {
* @param serverUrl The server URL to log.
* @param serverCount The number of server(s) the use own.
*/
fun logServerSwitch(serverUrl: String, serverCount: Int)
fun logServerSwitch(serverUrl: String, serverCount: Int) {}
/**
* Logs the admin opening.
*/
fun logOpenAdmin() {}
}
......@@ -64,4 +64,10 @@ class AnalyticsManager @Inject constructor(
analytics.forEach { it.logServerSwitch(serverUrl, accounts.size) }
}
}
fun logOpenAdmin() {
if (analyticsTrackingInteractor.get()) {
analytics.forEach { it.logOpenAdmin() }
}
}
}
......@@ -2,13 +2,22 @@ package chat.rocket.android.analytics.event
sealed class ScreenViewEvent(val screenName: String) {
// Authentication
object OnBoarding : ScreenViewEvent("OnBoardingFragment")
object Server : ScreenViewEvent("ServerFragment")
object LoginOptions : ScreenViewEvent("LoginOptionsFragment")
object Login : ScreenViewEvent("LoginFragment")
object TwoFa : ScreenViewEvent("TwoFAFragment")
object SignUp : ScreenViewEvent("SignupFragment")
object RegisterUsername : ScreenViewEvent("RegisterUsernameFragment")
object ResetPassword : ScreenViewEvent("ResetPasswordFragment")
object About : ScreenViewEvent("AboutFragment")
object ChatRoom : ScreenViewEvent("ChatRoomFragment")
object ChatRooms : ScreenViewEvent("ChatRoomsFragment")
object CreateChannel : ScreenViewEvent("CreateChannelFragment")
object FavoriteMessages : ScreenViewEvent("FavoriteMessagesFragment")
object Files : ScreenViewEvent("FilesFragment")
object Login : ScreenViewEvent("LoginFragment")
object MemberBottomSheet : ScreenViewEvent("MemberBottomSheetFragment")
object Members : ScreenViewEvent("MembersFragment")
object Mentions : ScreenViewEvent("MentionsFragment")
......@@ -17,10 +26,5 @@ sealed class ScreenViewEvent(val screenName: String) {
object PinnedMessages : ScreenViewEvent("PinnedMessagesFragment")
object Preferences : ScreenViewEvent("PreferencesFragment")
object Profile : ScreenViewEvent("ProfileFragment")
object RegisterUsername : ScreenViewEvent("RegisterUsernameFragment")
object ResetPassword : ScreenViewEvent("ResetPasswordFragment")
object Server : ScreenViewEvent("ServerFragment")
object Settings : ScreenViewEvent("SettingsFragment")
object SignUp : ScreenViewEvent("SignupFragment")
object TwoFa : ScreenViewEvent("TwoFAFragment")
}
package chat.rocket.android.authentication.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.authentication.ui.AuthenticationActivity
import chat.rocket.android.dagger.qualifier.ForAuthentication
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
@Module
class AuthenticationModule {
@Provides
@PerActivity
fun provideAuthenticationNavigator(activity: AuthenticationActivity) = AuthenticationNavigator(activity)
fun provideAuthenticationNavigator(activity: AuthenticationActivity) =
AuthenticationNavigator(activity)
@Provides
@PerActivity
fun provideJob() = Job()
@Provides
@PerActivity
fun provideLifecycleOwner(activity: AuthenticationActivity): LifecycleOwner = activity
@Provides
@PerActivity
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy =
CancelStrategy(owner, jobs)
}
\ No newline at end of file
......@@ -3,34 +3,18 @@ package chat.rocket.android.authentication.login.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.authentication.login.presentation.LoginView
import chat.rocket.android.authentication.login.ui.LoginFragment
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
@Module
class LoginFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
fun loginView(frag: LoginFragment): LoginView = frag
@Provides
@PerFragment
fun loginView(frag: LoginFragment): LoginView {
return frag
}
@Provides
@PerFragment
fun provideLifecycleOwner(frag: LoginFragment): LifecycleOwner {
return frag
}
@Provides
@PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
fun provideLifecycleOwner(frag: LoginFragment): LifecycleOwner = frag
}
\ No newline at end of file
......@@ -5,259 +5,34 @@ import chat.rocket.android.core.behaviours.MessageView
interface LoginView : LoadingView, MessageView {
/**
* Shows the form view (i.e the username/email and password fields) if it is enabled by the server settings.
*
* REMARK: We must set up the login button listener [setupLoginButtonListener].
* Remember to enable [enableUserInput] or disable [disableUserInput] the view interaction for the user when submitting the form.
*/
fun showFormView()
/**
* Hides the form view.
*/
fun hideFormView()
/**
* Setups the login button when tapped.
*/
fun setupLoginButtonListener()
/**
* Enables the view interactions for the user.
*/
fun enableUserInput()
/**
* Disables the view interactions for the user.
*/
fun disableUserInput()
/**
* Shows the CAS button if the sign in/sign out via CAS protocol is enabled by the server settings.
*
* REMARK: We must set up the CAS button listener before showing it [setupCasButtonListener].
*/
fun showCasButton()
/**
* Hides the CAS button.
*/
fun hideCasButton()
/**
* Setups the CAS button when tapped.
*
* @param casUrl The CAS URL to authenticate with.
* @param casToken The requested token to be sent to the CAS server.
*/
fun setupCasButtonListener(casUrl: String, casToken: String)
/**
* Shows the sign up view if the new users registration is enabled by the server settings.
*
* REMARK: We must set up the sign up view listener [setupSignUpView].
*/
fun showSignUpView()
/**
* Setups the sign up view when tapped.
*/
fun setupSignUpView()
/**
* Shows the forgot password view if enabled by the server settings.
*
* REMARK: We must set up the forgot password view listener [setupForgotPasswordView].
*/
fun showForgotPasswordView()
/**
* Setups the forgot password view when tapped.
*/
fun setupForgotPasswordView()
/**
* Hides the sign up view.
*/
fun hideSignUpView()
/**
* Enables and shows the oauth view if there is login via social accounts enabled by the server settings.
*
* REMARK: We must show at maximum *three* social accounts views ([enableLoginByFacebook], [enableLoginByGithub], [enableLoginByGoogle],
* [enableLoginByLinkedin], [enableLoginByMeteor], [enableLoginByTwitter], [enableLoginByGitlab], [addCustomOauthServiceButton] or [addSamlServiceButton]) for the oauth view.
* If the possibility of login via social accounts exceeds 3 different ways we should set up the FAB ([setupFabListener]) to show the remaining view(s).
*/
fun enableOauthView()
/**
* Disables and hides the Oauth view if there is not login via social accounts enabled by the server settings.
*/
fun disableOauthView()
/**
* Shows the login button.
*/
fun showLoginButton()
/**
* Hides the login button.
*/
fun hideLoginButton()
/**
* Shows the "login by Facebook view if it is enable by the server settings.
*/
fun enableLoginByFacebook()
/**
* Shows the "login by Github" view if it is enable by the server settings.
*
* REMARK: We must set up the Github button listener before enabling it [setupGithubButtonListener].
*/
fun enableLoginByGithub()
/**
* Setups the Github button when tapped.
*
* @param githubUrl The Github OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
*/
fun setupGithubButtonListener(githubUrl: String, state: String)
/**
* Shows the "login by Google" view if it is enable by the server settings.
*
* REMARK: We must set up the Google button listener before enabling it [setupGoogleButtonListener].
*/
fun enableLoginByGoogle()
/**
* Setups the Google button when tapped.
*
* @param googleUrl The Google OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
*/
fun setupGoogleButtonListener(googleUrl: String, state: String)
/**
* Shows the "login by Linkedin" view if it is enable by the server settings.
*
* REMARK: We must set up the Linkedin button listener before enabling it [setupLinkedinButtonListener].
*/
fun enableLoginByLinkedin()
/**
* Setups the Linkedin button when tapped.
*
* @param linkedinUrl The Linkedin OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
*/
fun setupLinkedinButtonListener(linkedinUrl: String, state: String)
/**
* Setups the Facebook button when tapped.
*
* @param facebookOauthUrl The Facebook OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
*/
fun setupFacebookButtonListener(facebookOauthUrl: String, state: String)
/**
* Shows the "login by Meteor" view if it is enable by the server settings.
*/
fun enableLoginByMeteor()
/**
* Shows the "login by Twitter" view if it is enable by the server settings.
*/
fun enableLoginByTwitter()
/**
* Shows the "login by Gitlab" view if it is enable by the server settings.
*
* REMARK: We must set up the Gitlab button listener before enabling it [setupGitlabButtonListener].
*/
fun enableLoginByGitlab()
/**
* Setups the Gitlab button when tapped.
*
* @param gitlabUrl The Gitlab OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
*/
fun setupGitlabButtonListener(gitlabUrl: String, state: String)
/**
* Shows the "login by WordPress" view if it is enable by the server settings.
*
* REMARK: We must set up the Gitlab button listener before enabling it [setupWordpressButtonListener].
*/
fun enableLoginByWordpress()
/**
* Setups the WordPress button when tapped.
*
* @param wordpressUrl The WordPress OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
*/
fun setupWordpressButtonListener(wordpressUrl: String, state: String)
/**
* Adds a custom OAuth button in the oauth view.
*
* @customOauthUrl The custom OAuth url to sets up the button (the listener).
* @state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
* @serviceName The custom OAuth service name.
* @serviceNameColor The custom OAuth service name color (just stylizing).
* @buttonColor The custom OAuth button color (just stylizing).
* @see [enableOauthView]
*/
fun addCustomOauthServiceButton(
customOauthUrl: String,
state: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
)
/**
* Adds a SAML button in the oauth view.
*
* @samlUrl The SAML url to sets up the button (the listener).
* @serviceName The SAML service name.
* @serviceNameColor The SAML service name color (just stylizing).
* @buttonColor The SAML button color (just stylizing).
* @see [enableOauthView]
* Saves Google Smart Lock credentials.
*/
fun addSamlServiceButton(
samlUrl: String,
samlToken: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
)
fun saveSmartLockCredentials(id: String, password: String)
/**
* Setups the FloatingActionButton to show more social accounts views (expanding the oauth view interface to show the remaining view(s)).
* Enables the button to login when the user inputs an username and a password.
*/
fun setupFabListener()
fun setupGlobalListener()
fun enableButtonLogin()
/**
* Alerts the user about a wrong inputted username or email.
* Disables the button to login when there is not an entered/not blank username or password by
* the user (i.e. The fields are empty/blank)
*/
fun alertWrongUsernameOrEmail()
fun disableButtonLogin()
/**
* Alerts the user about a wrong inputted password.
* Enables the forget password button after requesting a processing to log in.
*/
fun alertWrongPassword()
fun enableButtonForgetPassword()
/**
* Saves Google Smart Lock credentials.
* Disables the forget password button when requesting a processing to log in.
*/
fun saveSmartLockCredentials(id: String, password: String)
}
\ No newline at end of file
fun disableButtonForgetPassword()
}
package chat.rocket.android.authentication.loginoptions.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.authentication.loginoptions.presentation.LoginOptionsView
import chat.rocket.android.authentication.loginoptions.ui.LoginOptionsFragment
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.Provides
@Module
class LoginOptionsFragmentModule {
@Provides
@PerFragment
fun loginOptionsView(frag: LoginOptionsFragment): LoginOptionsView = frag
@Provides
@PerFragment
fun provideLifecycleOwner(frag: LoginOptionsFragment): LifecycleOwner = frag
}
\ No newline at end of file
package chat.rocket.android.authentication.loginoptions.di
import chat.rocket.android.authentication.loginoptions.ui.LoginOptionsFragment
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module abstract class LoginOptionsFragmentProvider {
@ContributesAndroidInjector(modules = [LoginOptionsFragmentModule::class])
@PerFragment
abstract fun providesLoginOptionFragment(): LoginOptionsFragment
}
\ No newline at end of file
package chat.rocket.android.authentication.loginoptions.presentation
import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.AuthenticationEvent
import chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.GetConnectingServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.SaveAccountInteractor
import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatAuthException
import chat.rocket.common.RocketChatException
import chat.rocket.common.model.Email
import chat.rocket.common.model.Token
import chat.rocket.common.model.User
import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.loginWithCas
import chat.rocket.core.internal.rest.loginWithOauth
import chat.rocket.core.internal.rest.loginWithSaml
import chat.rocket.core.internal.rest.me
import kotlinx.coroutines.experimental.delay
import java.util.concurrent.TimeUnit
import javax.inject.Inject
private const val TYPE_LOGIN_OAUTH = 1
private const val TYPE_LOGIN_CAS = 2
private const val TYPE_LOGIN_SAML = 3
private const val TYPE_LOGIN_DEEP_LINK = 4
class LoginOptionsPresenter @Inject constructor(
private val view: LoginOptionsView,
private val strategy: CancelStrategy,
private val factory: RocketChatClientFactory,
private val navigator: AuthenticationNavigator,
private val settingsInteractor: GetSettingsInteractor,
private val localRepository: LocalRepository,
private val saveCurrentServer: SaveCurrentServerInteractor,
private val saveAccountInteractor: SaveAccountInteractor,
private val analyticsManager: AnalyticsManager,
private val tokenRepository: TokenRepository,
serverInteractor: GetConnectingServerInteractor
) {
// TODO - we should validate the current server when opening the app, and have a nonnull get()
private var currentServer = serverInteractor.get()!!
private lateinit var client: RocketChatClient
private lateinit var settings: PublicSettings
private lateinit var credentialToken: String
private lateinit var credentialSecret: String
private lateinit var deepLinkUserId: String
private lateinit var deepLinkToken: String
private lateinit var loginMethod: AuthenticationEvent
fun toCreateAccount() = navigator.toCreateAccount()
fun toLoginWithEmail() = navigator.toLogin(currentServer)
fun authenticateWithOauth(oauthToken: String, oauthSecret: String) {
setupConnectionInfo(currentServer)
credentialToken = oauthToken
credentialSecret = oauthSecret
loginMethod = AuthenticationEvent.AuthenticationWithOauth
doAuthentication(TYPE_LOGIN_OAUTH)
}
fun authenticateWithCas(casToken: String) {
setupConnectionInfo(currentServer)
credentialToken = casToken
loginMethod = AuthenticationEvent.AuthenticationWithCas
doAuthentication(TYPE_LOGIN_CAS)
}
fun authenticateWithSaml(samlToken: String) {
setupConnectionInfo(currentServer)
credentialToken = samlToken
loginMethod = AuthenticationEvent.AuthenticationWithSaml
doAuthentication(TYPE_LOGIN_SAML)
}
fun authenticateWithDeepLink(deepLinkInfo: LoginDeepLinkInfo) {
val serverUrl = deepLinkInfo.url
setupConnectionInfo(serverUrl)
if (deepLinkInfo.userId != null && deepLinkInfo.token != null) {
deepLinkUserId = deepLinkInfo.userId
deepLinkToken = deepLinkInfo.token
tokenRepository.save(serverUrl, Token(deepLinkUserId, deepLinkToken))
loginMethod = AuthenticationEvent.AuthenticationWithDeeplink
doAuthentication(TYPE_LOGIN_DEEP_LINK)
}
}
private fun doAuthentication(loginType: Int) {
launchUI(strategy) {
view.showLoading()
try {
val token = retryIO("login") {
when (loginType) {
TYPE_LOGIN_OAUTH -> client.loginWithOauth(credentialToken, credentialSecret)
TYPE_LOGIN_CAS -> {
delay(3, TimeUnit.SECONDS)
client.loginWithCas(credentialToken)
}
TYPE_LOGIN_SAML -> {
delay(3, TimeUnit.SECONDS)
client.loginWithSaml(credentialToken)
}
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 AuthenticationEvent Deep Link Credentials...")
}
}
else -> {
throw IllegalStateException(
"Expected TYPE_LOGIN_USER_EMAIL, " +
"TYPE_LOGIN_CAS,TYPE_LOGIN_SAML, TYPE_LOGIN_OAUTH or " +
"TYPE_LOGIN_DEEP_LINK"
)
}
}
}
val myself = retryIO("me()") { client.me() }
myself.username?.let { username ->
val user = User(
id = myself.id,
roles = myself.roles,
status = myself.status,
name = myself.name,
emails = myself.emails?.map { Email(it.address ?: "", it.verified) },
username = myself.username,
utcOffset = myself.utcOffset
)
localRepository.saveCurrentUser(url = currentServer, user = user)
saveCurrentServer.save(currentServer)
saveAccount(username)
saveToken(token)
analyticsManager.logLogin(loginMethod, true)
navigator.toChatList()
}.ifNull {
if (loginType == TYPE_LOGIN_OAUTH) {
navigator.toRegisterUsername(token.userId, token.authToken)
}
}
} catch (exception: RocketChatException) {
analyticsManager.logLogin(loginMethod, false)
exception.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
}
}
}
private fun setupConnectionInfo(serverUrl: String) {
currentServer = serverUrl
client = factory.create(currentServer)
settings = settingsInteractor.get(currentServer)
}
private suspend fun saveAccount(username: String) {
val icon = settings.favicon()?.let {
currentServer.serverLogoUrl(it)
}
val logo = settings.wideTile()?.let {
currentServer.serverLogoUrl(it)
}
val thumb = currentServer.avatarUrl(username)
val account = Account(currentServer, icon, logo, username, thumb)
saveAccountInteractor.save(account)
}
private fun saveToken(token: Token) = tokenRepository.save(currentServer, token)
}
\ No newline at end of file
package chat.rocket.android.authentication.onboarding.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.authentication.onboarding.presentation.OnBoardingView
import chat.rocket.android.authentication.onboarding.ui.OnBoardingFragment
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.Provides
@Module
class OnBoardingFragmentModule {
@Provides
@PerFragment
fun onBoardingView(frag: OnBoardingFragment): OnBoardingView = frag
@Provides
@PerFragment
fun provideLifecycleOwner(frag: OnBoardingFragment): LifecycleOwner = frag
}
\ No newline at end of file
package chat.rocket.android.authentication.onboarding.di
import chat.rocket.android.authentication.onboarding.ui.OnBoardingFragment
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class OnBoardingFragmentProvider {
@ContributesAndroidInjector(modules = [OnBoardingFragmentModule::class])
@PerFragment
abstract fun provideOnBoardingFragment(): OnBoardingFragment
}
\ No newline at end of file
package chat.rocket.android.authentication.onboarding.presentation
import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView
interface OnBoardingView : LoadingView, MessageView
\ No newline at end of file
......@@ -3,34 +3,18 @@ package chat.rocket.android.authentication.registerusername.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.authentication.registerusername.presentation.RegisterUsernameView
import chat.rocket.android.authentication.registerusername.ui.RegisterUsernameFragment
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
@Module
class RegisterUsernameFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
fun registerUsernameView(frag: RegisterUsernameFragment): RegisterUsernameView = frag
@Provides
@PerFragment
fun registerUsernameView(frag: RegisterUsernameFragment): RegisterUsernameView {
return frag
}
@Provides
@PerFragment
fun provideLifecycleOwner(frag: RegisterUsernameFragment): LifecycleOwner {
return frag
}
@Provides
@PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
fun provideLifecycleOwner(frag: RegisterUsernameFragment): LifecycleOwner = frag
}
\ No newline at end of file
......@@ -6,7 +6,12 @@ import chat.rocket.android.core.behaviours.MessageView
interface RegisterUsernameView : LoadingView, MessageView {
/**
* Alerts the user about a blank username.
* Enables the button to set the username if the user entered at least one character.
*/
fun alertBlankUsername()
fun enableButtonUseThisUsername()
/**
* Disables the button to set the username when there is no character entered by the user.
*/
fun disableButtonUseThisUsername()
}
\ No newline at end of file
......@@ -9,4 +9,15 @@ interface ServerView : LoadingView, MessageView, VersionCheckView {
* Shows an invalid server URL message.
*/
fun showInvalidServerUrlMessage()
/**
* Enables the button to connect to the server when the user inputs a valid url.
*/
fun enableButtonConnect()
/**
* Disables the button to connect to the server when the server address entered by the user
* is not a valid url.
*/
fun disableButtonConnect()
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment