Unverified Commit 8c65d4a5 authored by Filipe de Lima Brito's avatar Filipe de Lima Brito Committed by GitHub

Merge pull request #1595 from RocketChat/new/answers-analytics

[NEW] Analytics for Answer (Fabric).
parents 9e86c3dc ba40ed52
......@@ -99,10 +99,8 @@ dependencies {
implementation libraries.appCompat
implementation libraries.recyclerview
implementation libraries.material
implementation libraries.constraintlayout
implementation libraries.cardview
implementation libraries.flexbox
implementation libraries.browser
implementation libraries.androidKtx
......@@ -112,6 +110,9 @@ dependencies {
kapt libraries.daggerProcessor
kapt libraries.daggerAndroidApt
implementation libraries.flexbox
implementation libraries.material
implementation libraries.room
kapt libraries.roomProcessor
implementation libraries.lifecycleExtensions
......@@ -144,12 +145,12 @@ dependencies {
implementation "com.github.luciofm:livedata-ktx:b1e8bbc25a"
// Proprietary libraries
playImplementation libraries.fcm
playImplementation libraries.firebaseAnalytics
playImplementation libraries.playServicesAuth
playImplementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') {
transitive = true
}
playImplementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') { transitive = true }
playImplementation('com.crashlytics.sdk.android:answers:1.4.2@aar') { transitive = true }
testImplementation libraries.junit
testImplementation libraries.truth
......
......@@ -2,6 +2,6 @@ package chat.rocket.android.util
import android.content.Context
fun setupCrashlytics(context: Context) {
//Do absolutely nothing
fun setupFabric(context: Context) {
//Do absolutely nothing
}
package chat.rocket.android.util
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.main.presentation.MainPresenter
fun refreshFCMToken(presenter: MainPresenter) {
......
......@@ -4,29 +4,37 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import chat.rocket.android.BuildConfig
import chat.rocket.android.R
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.fragment_about.*
import javax.inject.Inject
class AboutFragment : Fragment() {
internal const val TAG_ABOUT_FRAGMENT = "AboutFragment"
companion object {
fun newInstance() = AboutFragment()
}
class AboutFragment : Fragment() {
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_about, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupViews()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.About)
}
}
private fun setupViews() {
......@@ -36,16 +44,14 @@ class AboutFragment : Fragment() {
}
private fun setupToolbar() {
val toolbar = (activity as MainActivity).toolbar
toolbar.title = getString(R.string.title_about)
toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
toolbar.setNavigationOnClickListener {
this.activity?.onBackPressed()
with((activity as MainActivity).toolbar) {
title = getString(R.string.title_about)
setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
setNavigationOnClickListener { activity?.onBackPressed() }
}
}
override fun onStop() {
super.onStop()
(activity as MainActivity).toolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp)
companion object {
fun newInstance() = AboutFragment()
}
}
......@@ -19,7 +19,7 @@ import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.SITE_URL
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.emoji.EmojiRepository
import chat.rocket.android.util.setupCrashlytics
import chat.rocket.android.util.setupFabric
import com.facebook.drawee.backends.pipeline.DraweeConfig
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.imagepipeline.core.ImagePipelineConfig
......@@ -86,7 +86,7 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
AndroidThreeTen.init(this)
EmojiRepository.load(this)
setupCrashlytics(this)
setupFabric(this)
setupFresco()
setupTimber()
......
......@@ -5,30 +5,8 @@ import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.OauthHelper
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.GetAccountsInteractor
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.casLoginUrl
import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.gitlabUrl
import chat.rocket.android.server.domain.isCasAuthenticationEnabled
import chat.rocket.android.server.domain.isFacebookAuthenticationEnabled
import chat.rocket.android.server.domain.isGithubAuthenticationEnabled
import chat.rocket.android.server.domain.isGitlabAuthenticationEnabled
import chat.rocket.android.server.domain.isGoogleAuthenticationEnabled
import chat.rocket.android.server.domain.isLdapAuthenticationEnabled
import chat.rocket.android.server.domain.isLinkedinAuthenticationEnabled
import chat.rocket.android.server.domain.isLoginFormEnabled
import chat.rocket.android.server.domain.isWordpressAuthenticationEnabled
import chat.rocket.android.server.domain.isPasswordResetEnabled
import chat.rocket.android.server.domain.isRegistrationEnabledForNewUsers
import chat.rocket.android.server.domain.wordpressUrl
import chat.rocket.android.server.domain.*
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
......@@ -40,6 +18,8 @@ import chat.rocket.android.util.extensions.parseColor
import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.samlUrl
import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.AuthenticationEvent
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatAuthException
import chat.rocket.common.RocketChatException
......@@ -82,6 +62,7 @@ class LoginPresenter @Inject constructor(
private val localRepository: LocalRepository,
private val getAccountsInteractor: GetAccountsInteractor,
private val settingsInteractor: GetSettingsInteractor,
private val analyticsTrackingInteractor: AnalyticsTrackingInteractor,
serverInteractor: GetConnectingServerInteractor,
private val saveCurrentServer: SaveCurrentServerInteractor,
private val saveAccountInteractor: SaveAccountInteractor,
......@@ -97,6 +78,7 @@ class LoginPresenter @Inject constructor(
private lateinit var credentialSecret: String
private lateinit var deepLinkUserId: String
private lateinit var deepLinkToken: String
private lateinit var loginMethod: AuthenticationEvent
fun setupView() {
setupConnectionInfo(currentServer)
......@@ -118,6 +100,7 @@ class LoginPresenter @Inject constructor(
else -> {
this.usernameOrEmail = usernameOrEmail
this.password = password
loginMethod = AuthenticationEvent.AuthenticationWithUserAndPassword
doAuthentication(TYPE_LOGIN_USER_EMAIL)
}
}
......@@ -125,17 +108,20 @@ class LoginPresenter @Inject constructor(
fun authenticateWithCas(casToken: String) {
credentialToken = casToken
loginMethod = AuthenticationEvent.AuthenticationWithCas
doAuthentication(TYPE_LOGIN_CAS)
}
fun authenticateWithSaml(samlToken: String) {
credentialToken = samlToken
loginMethod = AuthenticationEvent.AuthenticationWithSaml
doAuthentication(TYPE_LOGIN_SAML)
}
fun authenticateWithOauth(oauthToken: String, oauthSecret: String) {
credentialToken = oauthToken
credentialSecret = oauthSecret
loginMethod = AuthenticationEvent.AuthenticationWithOauth
doAuthentication(TYPE_LOGIN_OAUTH)
}
......@@ -146,6 +132,7 @@ class LoginPresenter @Inject constructor(
deepLinkUserId = deepLinkInfo.userId
deepLinkToken = deepLinkInfo.token
tokenRepository.save(serverUrl, Token(deepLinkUserId, deepLinkToken))
loginMethod = AuthenticationEvent.AuthenticationWithDeeplink
doAuthentication(TYPE_LOGIN_DEEP_LINK)
} else {
// If we don't have the login credentials, just go through normal setup and user input.
......@@ -446,7 +433,7 @@ class LoginPresenter @Inject constructor(
if (myself.id == deepLinkUserId) {
Token(deepLinkUserId, deepLinkToken)
} else {
throw RocketChatAuthException("Invalid Authentication Deep Link Credentials...")
throw RocketChatAuthException("Invalid AuthenticationEvent Deep Link Credentials...")
}
}
else -> {
......@@ -465,11 +452,14 @@ class LoginPresenter @Inject constructor(
username = myself.username,
utcOffset = myself.utcOffset
)
localRepository.saveCurrentUser(url = currentServer, user = user)
localRepository.saveCurrentUser(currentServer, user)
saveCurrentServer.save(currentServer)
saveAccount(myself.username!!)
saveToken(token)
registerPushToken()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logLogin(loginMethod, true)
}
if (loginType == TYPE_LOGIN_USER_EMAIL) {
view.saveSmartLockCredentials(usernameOrEmail, password)
}
......@@ -483,6 +473,9 @@ class LoginPresenter @Inject constructor(
navigator.toTwoFA(usernameOrEmail, password)
}
else -> {
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logLogin(loginMethod, false)
}
exception.message?.let {
view.showMessage(it)
}.ifNull {
......
......@@ -23,7 +23,10 @@ import chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import chat.rocket.android.authentication.login.presentation.LoginPresenter
import chat.rocket.android.authentication.login.presentation.LoginView
import chat.rocket.android.helper.*
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.android.webview.sso.ui.INTENT_SSO_TOKEN
import chat.rocket.android.webview.sso.ui.ssoWebViewIntent
import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET
......@@ -34,6 +37,7 @@ import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_log_in.*
import javax.inject.Inject
internal const val TAG_LOGIN_FRAGMENT = "LoginFragment"
internal const val REQUEST_CODE_FOR_SIGN_IN_REQUIRED = 1
internal const val REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION = 2
internal const val REQUEST_CODE_FOR_SAVE_RESOLUTION = 3
......@@ -44,6 +48,8 @@ internal const val REQUEST_CODE_FOR_OAUTH = 6
class LoginFragment : Fragment(), LoginView {
@Inject
lateinit var presenter: LoginPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private var isOauthViewEnable = false
private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
areLoginOptionsNeeded()
......@@ -90,6 +96,10 @@ class LoginFragment : Fragment(), LoginView {
if (!hasCredentialsSupport()) {
image_key.isVisible = false
}
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Login)
}
}
override fun onDestroyView() {
......
......@@ -4,9 +4,14 @@ import android.content.Intent
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.TAG_LOGIN_FRAGMENT
import chat.rocket.android.authentication.registerusername.ui.RegisterUsernameFragment
import chat.rocket.android.authentication.registerusername.ui.TAG_REGISTER_USERNAME_FRAGMENT
import chat.rocket.android.authentication.resetpassword.ui.ResetPasswordFragment
import chat.rocket.android.authentication.resetpassword.ui.TAG_RESET_PASSWORD_FRAGMENT
import chat.rocket.android.authentication.signup.ui.SignupFragment
import chat.rocket.android.authentication.signup.ui.TAG_SIGNUP_FRAGMENT
import chat.rocket.android.authentication.twofactor.ui.TAG_TWO_FA_FRAGMENT
import chat.rocket.android.authentication.twofactor.ui.TwoFAFragment
import chat.rocket.android.authentication.ui.AuthenticationActivity
import chat.rocket.android.authentication.ui.newServerIntent
......@@ -19,13 +24,13 @@ import chat.rocket.android.webview.ui.webViewIntent
class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
fun toLogin() {
activity.addFragmentBackStack("LoginFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_LOGIN_FRAGMENT, R.id.fragment_container) {
LoginFragment.newInstance()
}
}
fun toLogin(deepLinkInfo: LoginDeepLinkInfo) {
activity.addFragmentBackStack("LoginFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_LOGIN_FRAGMENT, R.id.fragment_container) {
LoginFragment.newInstance(deepLinkInfo)
}
}
......@@ -35,19 +40,19 @@ class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
}
fun toTwoFA(username: String, password: String) {
activity.addFragmentBackStack("TwoFAFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_TWO_FA_FRAGMENT, R.id.fragment_container) {
TwoFAFragment.newInstance(username, password)
}
}
fun toSignUp() {
activity.addFragmentBackStack("SignupFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_SIGNUP_FRAGMENT, R.id.fragment_container) {
SignupFragment.newInstance()
}
}
fun toForgotPassword() {
activity.addFragmentBackStack("ResetPasswordFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_RESET_PASSWORD_FRAGMENT, R.id.fragment_container) {
ResetPasswordFragment.newInstance()
}
}
......@@ -58,7 +63,7 @@ class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
}
fun toRegisterUsername(userId: String, authToken: String) {
activity.addFragmentBackStack("RegisterUsernameFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_REGISTER_USERNAME_FRAGMENT, R.id.fragment_container) {
RegisterUsernameFragment.newInstance(userId, authToken)
}
}
......
......@@ -3,13 +3,24 @@ package chat.rocket.android.authentication.registerusername.presentation
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.*
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.server.domain.GetAccountsInteractor
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.extensions.avatarUrl
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.AuthenticationEvent
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException
import chat.rocket.common.model.Token
......@@ -27,6 +38,7 @@ class RegisterUsernamePresenter @Inject constructor(
private val factory: RocketChatClientFactory,
private val saveAccountInteractor: SaveAccountInteractor,
private val getAccountsInteractor: GetAccountsInteractor,
private val analyticsTrackingInteractor: AnalyticsTrackingInteractor,
serverInteractor: GetConnectingServerInteractor,
private val saveCurrentServer: SaveCurrentServerInteractor,
settingsInteractor: GetSettingsInteractor
......@@ -51,9 +63,15 @@ class RegisterUsernamePresenter @Inject constructor(
saveCurrentServer.save(currentServer)
tokenRepository.save(currentServer, Token(userId, authToken))
registerPushToken()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logSignUp(AuthenticationEvent.AuthenticationWithOauth, true)
}
navigator.toChatList()
}
} catch (exception: RocketChatException) {
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logSignUp(AuthenticationEvent.AuthenticationWithOauth, false)
}
exception.message?.let {
view.showMessage(it)
}.ifNull {
......
......@@ -10,14 +10,21 @@ import android.view.ViewGroup
import chat.rocket.android.R
import chat.rocket.android.authentication.registerusername.presentation.RegisterUsernamePresenter
import chat.rocket.android.authentication.registerusername.presentation.RegisterUsernameView
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_register_username.*
import javax.inject.Inject
internal const val TAG_REGISTER_USERNAME_FRAGMENT = "RegisterUsernameFragment"
class RegisterUsernameFragment : Fragment(), RegisterUsernameView {
@Inject
lateinit var presenter: RegisterUsernamePresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private lateinit var userId: String
private lateinit var authToken: String
......@@ -61,6 +68,10 @@ class RegisterUsernameFragment : Fragment(), RegisterUsernameView {
}
setupOnClickListener()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.RegisterUsername)
}
}
override fun alertBlankUsername() {
......
......@@ -11,18 +11,21 @@ import android.widget.Toast
import chat.rocket.android.R
import chat.rocket.android.authentication.resetpassword.presentation.ResetPasswordPresenter
import chat.rocket.android.authentication.resetpassword.presentation.ResetPasswordView
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_reset_password.*
import javax.inject.Inject
internal const val TAG_RESET_PASSWORD_FRAGMENT = "ResetPasswordFragment"
class ResetPasswordFragment : Fragment(), ResetPasswordView {
@Inject
lateinit var presenter: ResetPasswordPresenter
companion object {
fun newInstance() = ResetPasswordFragment()
}
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -48,6 +51,10 @@ class ResetPasswordFragment : Fragment(), ResetPasswordView {
}
setupOnClickListener()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.ResetPassword)
}
}
override fun alertBlankEmail() {
......@@ -131,4 +138,8 @@ class ResetPasswordFragment : Fragment(), ResetPasswordView {
presenter.resetPassword(text_email.textContent)
}
}
companion object {
fun newInstance() = ResetPasswordFragment()
}
}
\ No newline at end of file
......@@ -16,31 +16,27 @@ import chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import chat.rocket.android.authentication.server.presentation.ServerPresenter
import chat.rocket.android.authentication.server.presentation.ServerView
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.common.util.ifNull
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_server.*
import okhttp3.HttpUrl
import javax.inject.Inject
internal const val TAG_SERVER_FRAGMENT = "ServerFragment"
class ServerFragment : Fragment(), ServerView {
@Inject
lateinit var presenter: ServerPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private var deepLinkInfo: LoginDeepLinkInfo? = null
private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
text_server_url.isCursorVisible = KeyboardHelper.isSoftKeyboardShown(relative_layout.rootView)
}
companion object {
private const val DEEP_LINK_INFO = "DeepLinkInfo"
fun newInstance(deepLinkInfo: LoginDeepLinkInfo?) = ServerFragment().apply {
arguments = Bundle().apply {
putParcelable(DEEP_LINK_INFO, deepLinkInfo)
}
}
}
private var protocol = "https://"
private var ignoreChange = false
......@@ -100,6 +96,10 @@ class ServerFragment : Fragment(), ServerView {
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Server)
}
}
override fun onDestroyView() {
......@@ -217,4 +217,14 @@ class ServerFragment : Fragment(), ServerView {
}
}
}
companion object {
private const val DEEP_LINK_INFO = "DeepLinkInfo"
fun newInstance(deepLinkInfo: LoginDeepLinkInfo?) = ServerFragment().apply {
arguments = Bundle().apply {
putParcelable(DEEP_LINK_INFO, deepLinkInfo)
}
}
}
}
\ No newline at end of file
......@@ -3,11 +3,25 @@ package chat.rocket.android.authentication.signup.presentation
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.*
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.server.domain.GetAccountsInteractor
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.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.*
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.privacyPolicyUrl
import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.extensions.termsOfServiceUrl
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.AuthenticationEvent
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException
import chat.rocket.common.util.ifNull
......@@ -25,6 +39,7 @@ class SignupPresenter @Inject constructor(
private val localRepository: LocalRepository,
private val serverInteractor: GetConnectingServerInteractor,
private val saveCurrentServerInteractor: SaveCurrentServerInteractor,
private val analyticsTrackingInteractor: AnalyticsTrackingInteractor,
private val factory: RocketChatClientFactory,
private val saveAccountInteractor: SaveAccountInteractor,
private val getAccountsInteractor: GetAccountsInteractor,
......@@ -66,9 +81,21 @@ class SignupPresenter @Inject constructor(
localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, me.username)
saveAccount(me)
registerPushToken()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logSignUp(
AuthenticationEvent.AuthenticationWithUserAndPassword,
true
)
}
view.saveSmartLockCredentials(username, password)
navigator.toChatList()
} catch (exception: RocketChatException) {
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logSignUp(
AuthenticationEvent.AuthenticationWithUserAndPassword,
false
)
}
exception.message?.let {
view.showMessage(it)
}.ifNull {
......
......@@ -5,12 +5,12 @@ import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.text.style.ClickableSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.R.string.message_credentials_saved_successfully
import chat.rocket.android.authentication.signup.presentation.SignupPresenter
......@@ -18,16 +18,27 @@ import chat.rocket.android.authentication.signup.presentation.SignupView
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.TextHelper
import chat.rocket.android.helper.saveCredentials
import chat.rocket.android.util.extensions.*
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.util.extensions.shake
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.extensions.vibrateSmartPhone
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_sign_up.*
import javax.inject.Inject
internal const val TAG_SIGNUP_FRAGMENT = "SignupFragment"
internal const val SAVE_CREDENTIALS = 1
class SignupFragment : Fragment(), SignupView {
@Inject
lateinit var presenter: SignupPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
if (KeyboardHelper.isSoftKeyboardShown(relative_layout.rootView)) {
bottom_container.setVisible(false)
......@@ -40,10 +51,6 @@ class SignupFragment : Fragment(), SignupView {
}
}
companion object {
fun newInstance() = SignupFragment()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
......@@ -74,6 +81,10 @@ class SignupFragment : Fragment(), SignupView {
text_email.textContent
)
}
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.SignUp)
}
}
override fun onDestroyView() {
......@@ -154,9 +165,7 @@ class SignupFragment : Fragment(), SignupView {
}
override fun saveSmartLockCredentials(id: String, password: String) {
activity?.let {
it.saveCredentials(id, password)
}
activity?.saveCredentials(id, password)
}
private fun tintEditTextDrawableStart() {
......@@ -215,4 +224,8 @@ class SignupFragment : Fragment(), SignupView {
text_password.isEnabled = value
text_email.isEnabled = value
}
companion object {
fun newInstance() = SignupFragment()
}
}
......@@ -6,10 +6,12 @@ import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.AuthenticationEvent
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatAuthException
import chat.rocket.common.RocketChatException
......@@ -20,23 +22,30 @@ import chat.rocket.core.internal.rest.me
import chat.rocket.core.model.Myself
import javax.inject.Inject
class TwoFAPresenter @Inject constructor(private val view: TwoFAView,
private val strategy: CancelStrategy,
private val navigator: AuthenticationNavigator,
private val tokenRepository: TokenRepository,
private val localRepository: LocalRepository,
private val serverInteractor: GetConnectingServerInteractor,
private val saveCurrentServerInteractor: SaveCurrentServerInteractor,
private val factory: RocketChatClientFactory,
private val saveAccountInteractor: SaveAccountInteractor,
private val getAccountsInteractor: GetAccountsInteractor,
settingsInteractor: GetSettingsInteractor) {
class TwoFAPresenter @Inject constructor(
private val view: TwoFAView,
private val strategy: CancelStrategy,
private val navigator: AuthenticationNavigator,
private val tokenRepository: TokenRepository,
private val localRepository: LocalRepository,
private val serverInteractor: GetConnectingServerInteractor,
private val saveCurrentServerInteractor: SaveCurrentServerInteractor,
private val analyticsTrackingInteractor: AnalyticsTrackingInteractor,
private val factory: RocketChatClientFactory,
private val saveAccountInteractor: SaveAccountInteractor,
private val getAccountsInteractor: GetAccountsInteractor,
settingsInteractor: GetSettingsInteractor
) {
private val currentServer = serverInteractor.get()!!
private val client: RocketChatClient = factory.create(currentServer)
private var settings: PublicSettings = settingsInteractor.get(serverInteractor.get()!!)
// TODO: If the usernameOrEmail and password was informed by the user on the previous screen, then we should pass only the pin, like this: fun authenticate(pin: EditText)
fun authenticate(usernameOrEmail: String, password: String, twoFactorAuthenticationCode: String) {
fun authenticate(
usernameOrEmail: String,
password: String,
twoFactorAuthenticationCode: String
) {
val server = serverInteractor.get()
when {
server == null -> {
......@@ -59,11 +68,23 @@ class TwoFAPresenter @Inject constructor(private val view: TwoFAView,
saveCurrentServerInteractor.save(currentServer)
tokenRepository.save(server, token)
registerPushToken()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logLogin(
AuthenticationEvent.AuthenticationWithUserAndPassword,
true
)
}
navigator.toChatList()
} catch (exception: RocketChatException) {
if (exception is RocketChatAuthException) {
view.alertInvalidTwoFactorAuthenticationCode()
} else {
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logLogin(
AuthenticationEvent.AuthenticationWithUserAndPassword,
false
)
}
exception.message?.let {
view.showMessage(it)
}.ifNull {
......
......@@ -4,37 +4,38 @@ import DrawableHelper
import android.content.Context
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.authentication.twofactor.presentation.TwoFAPresenter
import chat.rocket.android.authentication.twofactor.presentation.TwoFAView
import chat.rocket.android.util.extensions.*
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.util.extensions.shake
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.extensions.vibrateSmartPhone
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_two_fa.*
import javax.inject.Inject
internal const val TAG_TWO_FA_FRAGMENT = "TwoFAFragment"
class TwoFAFragment : Fragment(), TwoFAView {
@Inject lateinit var presenter: TwoFAPresenter
@Inject
lateinit var presenter: TwoFAPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
lateinit var username: String
lateinit var password: String
// TODO - we could create an in memory repository to save username and password.
companion object {
private const val USERNAME = "username"
private const val PASSWORD = "password"
fun newInstance(username: String, password: String) = TwoFAFragment().apply {
arguments = Bundle(2).apply {
putString(USERNAME, username)
putString(PASSWORD, password)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
......@@ -44,7 +45,11 @@ class TwoFAFragment : Fragment(), TwoFAView {
password = arguments?.getString(PASSWORD) ?: ""
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = container?.inflate(R.layout.fragment_authentication_two_fa)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = container?.inflate(R.layout.fragment_authentication_two_fa)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
......@@ -60,6 +65,10 @@ class TwoFAFragment : Fragment(), TwoFAView {
}
setupOnClickListener()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.TwoFa)
}
}
override fun alertBlankTwoFactorAuthenticationCode() {
......@@ -103,7 +112,8 @@ class TwoFAFragment : Fragment(), TwoFAView {
private fun tintEditTextDrawableStart() {
ui {
val lockDrawable = DrawableHelper.getDrawableFromId(R.drawable.ic_vpn_key_black_24dp, it)
val lockDrawable =
DrawableHelper.getDrawableFromId(R.drawable.ic_vpn_key_black_24dp, it)
DrawableHelper.wrapDrawable(lockDrawable)
DrawableHelper.tintDrawable(lockDrawable, it, R.color.colorDrawableTintGrey)
DrawableHelper.compoundDrawable(text_two_factor_auth, lockDrawable)
......@@ -120,4 +130,17 @@ class TwoFAFragment : Fragment(), TwoFAView {
presenter.authenticate(username, password, text_two_factor_auth.textContent)
}
}
// TODO - we could create an in memory repository to save username and password.
companion object {
private const val USERNAME = "username"
private const val PASSWORD = "password"
fun newInstance(username: String, password: String) = TwoFAFragment().apply {
arguments = Bundle(2).apply {
putString(USERNAME, username)
putString(PASSWORD, password)
}
}
}
}
......@@ -10,6 +10,7 @@ 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.server.ui.ServerFragment
import chat.rocket.android.authentication.server.ui.TAG_SERVER_FRAGMENT
import chat.rocket.android.util.extensions.addFragment
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
......@@ -64,7 +65,7 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
}
fun showServerInput(deepLinkInfo: LoginDeepLinkInfo?) {
addFragment("ServerFragment", R.id.fragment_container, allowStateLoss = true) {
addFragment(TAG_SERVER_FRAGMENT, R.id.fragment_container, allowStateLoss = true) {
ServerFragment.newInstance(deepLinkInfo)
}
}
......
......@@ -6,7 +6,6 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.chatinformation.ui.MessageInfoFragment.Companion.TAG_MESSAGE_INFO_FRAGMENT
import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.util.extensions.textContent
import dagger.android.AndroidInjection
......
......@@ -13,10 +13,11 @@ import chat.rocket.android.chatinformation.adapter.ReadReceiptAdapter
import chat.rocket.android.chatinformation.presentation.MessageInfoPresenter
import chat.rocket.android.chatinformation.presentation.MessageInfoView
import chat.rocket.android.chatinformation.viewmodel.ReadReceiptViewModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.util.extensions.showToast
import chat.rocket.core.model.ReadReceipt
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_message_info.*
import javax.inject.Inject
......@@ -29,13 +30,14 @@ fun newInstance(messageId: String): Fragment {
}
}
internal const val TAG_MESSAGE_INFO_FRAGMENT = "MessageInfoFragment"
private const val BUNDLE_MESSAGE_ID = "message_id"
class MessageInfoFragment : Fragment(), MessageInfoView {
@Inject
lateinit var presenter: MessageInfoPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private lateinit var adapter: ReadReceiptAdapter
private lateinit var messageId: String
......@@ -64,6 +66,10 @@ class MessageInfoFragment : Fragment(), MessageInfoView {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
presenter.loadReadReceipts(messageId = messageId)
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.MessageInfo)
}
}
private fun setupRecyclerView() {
......@@ -93,8 +99,4 @@ class MessageInfoFragment : Fragment(), MessageInfoView {
override fun showReadReceipts(messageReceipts: List<ReadReceiptViewModel>) {
adapter.addAll(messageReceipts)
}
companion object {
const val TAG_MESSAGE_INFO_FRAGMENT = "MessageInfoFragment"
}
}
......@@ -4,37 +4,42 @@ import chat.rocket.android.R
import chat.rocket.android.chatinformation.ui.messageInformationIntent
import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatroom.ui.chatRoomIntent
import chat.rocket.android.favoritemessages.ui.TAG_FAVORITE_MESSAGES_FRAGMENT
import chat.rocket.android.files.ui.TAG_FILES_FRAGMENT
import chat.rocket.android.members.ui.TAG_MEMBERS_FRAGMENT
import chat.rocket.android.mentions.ui.TAG_MENTIONS_FRAGMENT
import chat.rocket.android.pinnedmessages.ui.TAG_PINNED_MESSAGES_FRAGMENT
import chat.rocket.android.server.ui.changeServerIntent
import chat.rocket.android.util.extensions.addFragmentBackStack
class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
fun toMembersList(chatRoomId: String) {
activity.addFragmentBackStack("MembersFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_MEMBERS_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.members.ui.newInstance(chatRoomId)
}
}
fun toMentions(chatRoomId: String) {
activity.addFragmentBackStack("MentionsFragment", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_MENTIONS_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.mentions.ui.newInstance(chatRoomId)
}
}
fun toPinnedMessageList(chatRoomId: String) {
activity.addFragmentBackStack("PinnedMessages", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_PINNED_MESSAGES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.pinnedmessages.ui.newInstance(chatRoomId)
}
}
fun toFavoriteMessageList(chatRoomId: String) {
activity.addFragmentBackStack("FavoriteMessages", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_FAVORITE_MESSAGES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.favoritemessages.ui.newInstance(chatRoomId)
}
}
fun toFileList(chatRoomId: String) {
activity.addFragmentBackStack("Files", R.id.fragment_container) {
activity.addFragmentBackStack(TAG_FILES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.files.ui.newInstance(chatRoomId)
}
}
......
......@@ -17,6 +17,7 @@ import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.helper.MessageHelper
import chat.rocket.android.helper.UserHelper
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.JobSchedulerInteractor
......@@ -33,6 +34,8 @@ import chat.rocket.android.server.infraestructure.state
import chat.rocket.android.util.extension.compressImageAndGetInputStream
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.SubscriptionTypeEvent
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException
import chat.rocket.common.model.RoomType
......@@ -90,6 +93,7 @@ class ChatRoomPresenter @Inject constructor(
private val usersRepository: UsersRepository,
private val roomsRepository: RoomRepository,
private val localRepository: LocalRepository,
private val analyticsTrackingInteractor: AnalyticsTrackingInteractor,
private val userHelper: UserHelper,
private val mapper: UiModelMapper,
private val jobSchedulerInteractor: JobSchedulerInteractor,
......@@ -107,7 +111,7 @@ class ChatRoomPresenter @Inject constructor(
private val messagesChannel = Channel<Message>()
private var chatRoomId: String? = null
private var chatRoomType: String? = null
private lateinit var chatRoomType: String
private var chatIsBroadcast: Boolean = false
private var chatRoles = emptyList<ChatRoomRole>()
private val stateChannel = Channel<State>()
......@@ -261,7 +265,7 @@ class ChatRoomPresenter @Inject constructor(
try {
// ignore message for now, will receive it on the stream
val id = UUID.randomUUID().toString()
val message = if (messageId == null) {
if (messageId == null) {
val username = userHelper.username()
val newMessage = Message(
id = id,
......@@ -291,11 +295,14 @@ class ChatRoomPresenter @Inject constructor(
messagesRepository.save(newMessage)
view.showNewMessage(
mapper.map(
newMessage,
newMessage,
RoomUiModel(roles = chatRoles, isBroadcast = chatIsBroadcast)
), false
)
client.sendMessage(id, chatRoomId, text)
if (analyticsTrackingInteractor.get()) {
logMessageSent(currentServer)
}
} catch (ex: Exception) {
// Ok, not very beautiful, but the backend sends us a not valid response
// When someone sends a message on a read-only channel, so we just ignore it
......@@ -363,6 +370,9 @@ class ChatRoomPresenter @Inject constructor(
inputStream
}
}
if (analyticsTrackingInteractor.get()) {
logMediaUploaded(mimeType)
}
}
}
}
......@@ -934,12 +944,45 @@ class ChatRoomPresenter @Inject constructor(
retryIO("toggleEmoji($messageId, $emoji)") {
client.toggleReaction(messageId, emoji.removeSurrounding(":"))
}
if (analyticsTrackingInteractor.get()) {
logReactionEvent()
}
} catch (ex: RocketChatException) {
Timber.e(ex)
}
}
}
private fun logReactionEvent() {
when {
roomTypeOf(chatRoomType) is RoomType.DirectMessage ->
AnalyticsManager.logReaction(SubscriptionTypeEvent.DirectMessage)
roomTypeOf(chatRoomType) is RoomType.Channel ->
AnalyticsManager.logReaction(SubscriptionTypeEvent.Channel)
else -> AnalyticsManager.logReaction(SubscriptionTypeEvent.Group)
}
}
private fun logMediaUploaded(mimeType: String) {
when {
roomTypeOf(chatRoomType) is RoomType.DirectMessage ->
AnalyticsManager.logMediaUploaded(SubscriptionTypeEvent.DirectMessage, mimeType)
roomTypeOf(chatRoomType) is RoomType.Channel ->
AnalyticsManager.logMediaUploaded(SubscriptionTypeEvent.Channel, mimeType)
else -> AnalyticsManager.logMediaUploaded(SubscriptionTypeEvent.Group, mimeType)
}
}
private fun logMessageSent(serverUrl: String) {
when {
roomTypeOf(chatRoomType) is RoomType.DirectMessage ->
AnalyticsManager.logMessageSent(SubscriptionTypeEvent.DirectMessage, serverUrl)
roomTypeOf(chatRoomType) is RoomType.Channel ->
AnalyticsManager.logMessageSent(SubscriptionTypeEvent.Channel, serverUrl)
else -> AnalyticsManager.logMessageSent(SubscriptionTypeEvent.Group, serverUrl)
}
}
fun showReactions(messageId: String) {
view.showReactionsPopup(messageId)
}
......
......@@ -6,8 +6,6 @@ import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import android.text.SpannableStringBuilder
import androidx.core.view.isVisible
import chat.rocket.android.R
import chat.rocket.android.chatroom.presentation.ChatRoomNavigator
import chat.rocket.android.server.domain.GetCurrentServerInteractor
......@@ -169,8 +167,4 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
super.onBackPressed()
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
}
companion object {
const val TAG_CHAT_ROOM_FRAGMENT = "ChatRoomFragment"
}
}
\ No newline at end of file
......@@ -55,6 +55,7 @@ import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.helper.ImageHelper
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.MessageParser
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extensions.circularRevealOrUnreveal
import chat.rocket.android.util.extensions.fadeIn
......@@ -65,6 +66,8 @@ import chat.rocket.android.util.extensions.rotateBy
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import chat.rocket.core.internal.realtime.socket.model.State
......@@ -107,6 +110,8 @@ fun newInstance(
}
}
internal const val TAG_CHAT_ROOM_FRAGMENT = "ChatRoomFragment"
private const val BUNDLE_CHAT_ROOM_ID = "chat_room_id"
private const val BUNDLE_CHAT_ROOM_NAME = "chat_room_name"
private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
......@@ -132,6 +137,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
lateinit var presenter: ChatRoomPresenter
@Inject
lateinit var parser: MessageParser
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private lateinit var adapter: ChatRoomAdapter
internal lateinit var chatRoomId: String
private lateinit var chatRoomName: String
......@@ -228,6 +235,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
it.showToolbarTitle(chatRoomName)
it.showToolbarChatRoomIcon(chatRoomType)
}
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.ChatRoom)
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
......
......@@ -32,12 +32,15 @@ import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.helper.ChatRoomsSortOrder
import chat.rocket.android.helper.Constants
import chat.rocket.android.helper.SharedPreferenceHelper
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extension.onQueryTextListener
import chat.rocket.android.util.extensions.fadeIn
import chat.rocket.android.util.extensions.fadeOut
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.android.widget.DividerItemDecoration
import chat.rocket.core.internal.realtime.socket.model.State
import dagger.android.support.AndroidSupportInjection
......@@ -45,6 +48,8 @@ import kotlinx.android.synthetic.main.fragment_chat_rooms.*
import timber.log.Timber
import javax.inject.Inject
internal const val TAG_CHAT_ROOMS_FRAGMENT = "ChatRoomsFragment"
private const val BUNDLE_CHAT_ROOM_ID = "BUNDLE_CHAT_ROOM_ID"
class ChatRoomsFragment : Fragment(), ChatRoomsView {
......@@ -54,14 +59,12 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
lateinit var factory: ChatRoomsViewModelFactory
@Inject
lateinit var dbManager: DatabaseManager // TODO - remove when moving ChatRoom screen to DB
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
lateinit var viewModel: ChatRoomsViewModel
private var searchView: SearchView? = null
private var sortView: MenuItem? = null
private val handler = Handler()
private var chatRoomId: String? = null
private var progressDialog: ProgressDialog? = null
......@@ -108,6 +111,10 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
subscribeUi()
setupToolbar()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.ChatRooms)
}
}
private fun subscribeUi() {
......
......@@ -20,10 +20,13 @@ import chat.rocket.android.createchannel.presentation.CreateChannelView
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.members.adapter.MembersAdapter
import chat.rocket.android.members.uimodel.MemberUiModel
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import com.google.android.material.chip.Chip
......@@ -34,9 +37,13 @@ import kotlinx.android.synthetic.main.fragment_create_channel.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
internal const val TAG_CREATE_CHANNEL_FRAGMENT = "CreateChannelFragment"
class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback {
@Inject
lateinit var createChannelPresenter: CreateChannelPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private var actionMode: ActionMode? = null
private val adapter: MembersAdapter = MembersAdapter {
if (it.username != null) {
......@@ -69,6 +76,10 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback
setupViewListeners()
setupRecyclerView()
subscribeEditTexts()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.CreateChannel)
}
}
override fun onDestroyView() {
......
......@@ -25,6 +25,7 @@ import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.members.di.MembersFragmentProvider
import chat.rocket.android.mentions.di.MentionsFragmentProvider
import chat.rocket.android.pinnedmessages.di.PinnedMessagesFragmentProvider
import chat.rocket.android.preferences.di.PreferencesFragmentProvider
import chat.rocket.android.profile.di.ProfileFragmentProvider
import chat.rocket.android.server.di.ChangeServerModule
import chat.rocket.android.server.ui.ChangeServerActivity
......@@ -56,7 +57,8 @@ abstract class ActivityBuilder {
ChatRoomsFragmentProvider::class,
CreateChannelProvider::class,
ProfileFragmentProvider::class,
SettingsFragmentProvider::class
SettingsFragmentProvider::class,
PreferencesFragmentProvider::class
]
)
abstract fun bindMainActivity(): MainActivity
......
......@@ -23,6 +23,7 @@ import chat.rocket.android.push.GroupedPush
import chat.rocket.android.push.PushManager
import chat.rocket.android.server.domain.AccountsRepository
import chat.rocket.android.server.domain.ActiveUsersRepository
import chat.rocket.android.server.domain.AnalyticsTrackingRepository
import chat.rocket.android.server.domain.ChatRoomsRepository
import chat.rocket.android.server.domain.CurrentServerRepository
import chat.rocket.android.server.domain.GetAccountInteractor
......@@ -34,7 +35,6 @@ import chat.rocket.android.server.domain.MultiServerTokenRepository
import chat.rocket.android.server.domain.PermissionsRepository
import chat.rocket.android.server.domain.RoomRepository
import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.UsersRepository
import chat.rocket.android.server.infraestructure.JobSchedulerInteractorImpl
import chat.rocket.android.server.infraestructure.MemoryActiveUsersRepository
......@@ -45,6 +45,7 @@ import chat.rocket.android.server.infraestructure.SharedPreferencesAccountsRepos
import chat.rocket.android.server.infraestructure.SharedPreferencesMessagesRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesPermissionsRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesSettingsRepository
import chat.rocket.android.server.infraestructure.SharedPrefsAnalyticsTrackingRepository
import chat.rocket.android.server.infraestructure.SharedPrefsConnectingServerRepository
import chat.rocket.android.server.infraestructure.SharedPrefsCurrentServerRepository
import chat.rocket.android.util.AppJsonAdapterFactory
......@@ -56,6 +57,7 @@ import chat.rocket.common.model.TimestampAdapter
import chat.rocket.common.util.CalendarISO8601Converter
import chat.rocket.common.util.Logger
import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.TokenRepository
import chat.rocket.core.internal.AttachmentAdapterFactory
import chat.rocket.core.internal.ReactionsAdapter
import com.facebook.drawee.backends.pipeline.DraweeConfig
......@@ -163,6 +165,12 @@ class AppModule {
return SharedPrefsCurrentServerRepository(prefs)
}
@Provides
@Singleton
fun provideAnalyticsTrackingRepository(prefs: SharedPreferences): AnalyticsTrackingRepository {
return SharedPrefsAnalyticsTrackingRepository(prefs)
}
@Provides
@ForAuthentication
fun provideConnectingServerRepository(prefs: SharedPreferences): CurrentServerRepository {
......
......@@ -16,9 +16,12 @@ import chat.rocket.android.chatroom.uimodel.BaseUiModel
import chat.rocket.android.favoritemessages.presentation.FavoriteMessagesPresenter
import chat.rocket.android.favoritemessages.presentation.FavoriteMessagesView
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_favorite_messages.*
import javax.inject.Inject
......@@ -31,13 +34,16 @@ fun newInstance(chatRoomId: String): Fragment {
}
}
internal const val TAG_FAVORITE_MESSAGES_FRAGMENT = "FavoriteMessagesFragment"
private const val INTENT_CHAT_ROOM_ID = "chat_room_id"
class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView {
private lateinit var chatRoomId: String
private val adapter = ChatRoomAdapter(enableActions = false)
@Inject
lateinit var presenter: FavoriteMessagesPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private lateinit var chatRoomId: String
private val adapter = ChatRoomAdapter(enableActions = false)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -61,6 +67,10 @@ class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView {
super.onViewCreated(view, savedInstanceState)
setupToolbar()
presenter.loadFavoriteMessages(chatRoomId)
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.FavoriteMessages)
}
}
override fun showFavoriteMessages(favoriteMessages: List<BaseUiModel<*>>) {
......
......@@ -21,9 +21,12 @@ import chat.rocket.android.files.uimodel.FileUiModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.helper.ImageHelper
import chat.rocket.android.player.PlayerActivity
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_files.*
import javax.inject.Inject
......@@ -36,11 +39,14 @@ fun newInstance(chatRoomId: String): Fragment {
}
}
internal const val TAG_FILES_FRAGMENT = "FilesFragment"
private const val BUNDLE_CHAT_ROOM_ID = "chat_room_id"
class FilesFragment : Fragment(), FilesView {
@Inject
lateinit var presenter: FilesPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private val adapter: FilesAdapter =
FilesAdapter { fileUiModel -> presenter.openFile(fileUiModel) }
private val linearLayoutManager = LinearLayoutManager(context)
......@@ -68,6 +74,10 @@ class FilesFragment : Fragment(), FilesView {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
presenter.loadFiles(chatRoomId)
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Files)
}
}
override fun showFiles(dataSet: List<FileUiModel>, total: Long) {
......
......@@ -4,36 +4,40 @@ import chat.rocket.android.R
import chat.rocket.android.authentication.ui.newServerIntent
import chat.rocket.android.chatroom.ui.chatRoomIntent
import chat.rocket.android.chatrooms.ui.ChatRoomsFragment
import chat.rocket.android.chatrooms.ui.TAG_CHAT_ROOMS_FRAGMENT
import chat.rocket.android.createchannel.ui.CreateChannelFragment
import chat.rocket.android.createchannel.ui.TAG_CREATE_CHANNEL_FRAGMENT
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.profile.ui.ProfileFragment
import chat.rocket.android.profile.ui.TAG_PROFILE_FRAGMENT
import chat.rocket.android.server.ui.changeServerIntent
import chat.rocket.android.settings.ui.SettingsFragment
import chat.rocket.android.settings.ui.TAG_SETTINGS_FRAGMENT
import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.webview.adminpanel.ui.AdminPanelWebViewFragment
class MainNavigator(internal val activity: MainActivity) {
fun toChatList(chatRoomId: String? = null) {
activity.addFragment("ChatRoomsFragment", R.id.fragment_container) {
activity.addFragment(TAG_CHAT_ROOMS_FRAGMENT, R.id.fragment_container) {
ChatRoomsFragment.newInstance(chatRoomId)
}
}
fun toCreateChannel() {
activity.addFragment("CreateChannelFragment", R.id.fragment_container) {
activity.addFragment(TAG_CREATE_CHANNEL_FRAGMENT, R.id.fragment_container) {
CreateChannelFragment.newInstance()
}
}
fun toUserProfile() {
activity.addFragment("ProfileFragment", R.id.fragment_container) {
activity.addFragment(TAG_PROFILE_FRAGMENT, R.id.fragment_container) {
ProfileFragment.newInstance()
}
}
fun toSettings() {
activity.addFragment("SettingsFragment", R.id.fragment_container) {
activity.addFragment(TAG_SETTINGS_FRAGMENT, R.id.fragment_container) {
SettingsFragment.newInstance()
}
}
......@@ -69,7 +73,17 @@ class MainNavigator(internal val activity: MainActivity) {
activity.overridePendingTransition(R.anim.open_enter, R.anim.open_exit)
}
fun toNewServer(serverUrl: String? = null) {
/**
* Switches to a server, given a [serverUrl] or adds a new server (navigating to the
* AuthenticationActivity) if the user server list only contains one server and the
* user logs out from this server.
* NOTE: If the user has more than one server and logs out from the current server, then it will
* switch to the first server in the server list.
*
* @param serverUrl The server URL to switch from, or null in case user logs out from the
* current server.
*/
fun switchOrAddNewServer(serverUrl: String? = null) {
activity.startActivity(activity.changeServerIntent(serverUrl = serverUrl))
activity.finish()
}
......
......@@ -149,7 +149,7 @@ class MainPresenter @Inject constructor(
tokenRepository.remove(currentServer)
withContext(CommonPool) { dbManager.logout() }
navigator.toNewServer()
navigator.switchOrAddNewServer()
} catch (ex: Exception) {
Timber.d(ex, "Error cleaning up the session...")
}
......@@ -170,7 +170,7 @@ class MainPresenter @Inject constructor(
fun changeServer(serverUrl: String) {
if (currentServer != serverUrl) {
navigator.toNewServer(serverUrl)
navigator.switchOrAddNewServer(serverUrl)
} else {
view.closeServerSelection()
}
......
package chat.rocket.android.members.presentation
import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.members.ui.TAG_MEMBER_BOTTOM_SHEET_FRAGMENT
import chat.rocket.android.members.ui.newInstance
class MembersNavigator(internal val activity: ChatRoomActivity) {
......@@ -8,7 +9,7 @@ class MembersNavigator(internal val activity: ChatRoomActivity) {
fun toMemberDetails(avatarUri: String, realName: String, username: String, email: String, utcOffset: String) {
activity.apply {
newInstance(avatarUri, realName, username, email, utcOffset)
.show(supportFragmentManager, "MemberBottomSheetFragment")
.show(supportFragmentManager, TAG_MEMBER_BOTTOM_SHEET_FRAGMENT)
}
}
}
package chat.rocket.android.members.ui
import android.os.Bundle
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import chat.rocket.android.R
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.content
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.fragment_member_bottom_sheet.*
import javax.inject.Inject
fun newInstance(avatarUri: String,
realName: String,
username: String,
email: String,
utcOffset: String): BottomSheetDialogFragment {
fun newInstance(
avatarUri: String,
realName: String,
username: String,
email: String,
utcOffset: String
): BottomSheetDialogFragment {
return MemberBottomSheetFragment().apply {
arguments = Bundle(1).apply {
putString(BUNDLE_AVATAR_URI, avatarUri)
......@@ -27,13 +33,17 @@ fun newInstance(avatarUri: String,
}
}
internal const val TAG_MEMBER_BOTTOM_SHEET_FRAGMENT = "MemberBottomSheetFragment"
private const val BUNDLE_AVATAR_URI = "avatar_uri"
private const val BUNDLE_REAL_NAME = "real_name"
private const val BUNDLE_USERNAME = "username"
private const val BUNDLE_EMAIL = "email"
private const val BUNDLE_UTC_OFFSET = "utc_offset"
class MemberBottomSheetFragment: BottomSheetDialogFragment() {
class MemberBottomSheetFragment : BottomSheetDialogFragment() {
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private lateinit var avatarUri: String
private lateinit var realName: String
private lateinit var username: String
......@@ -54,12 +64,21 @@ class MemberBottomSheetFragment: BottomSheetDialogFragment() {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
inflater.inflate(R.layout.fragment_member_bottom_sheet, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
showMemberDetails()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.MemberBottomSheet)
}
}
private fun showMemberDetails() {
......@@ -74,7 +93,7 @@ class MemberBottomSheetFragment: BottomSheetDialogFragment() {
text_member_email_address.isVisible = false
}
if (utcOffset.isNotEmpty()){
if (utcOffset.isNotEmpty()) {
text_member_utc.content = utcOffset
} else {
text_utc.isVisible = false
......
......@@ -16,9 +16,12 @@ import chat.rocket.android.members.adapter.MembersAdapter
import chat.rocket.android.members.presentation.MembersPresenter
import chat.rocket.android.members.presentation.MembersView
import chat.rocket.android.members.uimodel.MemberUiModel
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_members.*
import javax.inject.Inject
......@@ -31,11 +34,14 @@ fun newInstance(chatRoomId: String): Fragment {
}
}
internal const val TAG_MEMBERS_FRAGMENT = "MembersFragment"
private const val BUNDLE_CHAT_ROOM_ID = "chat_room_id"
class MembersFragment : Fragment(), MembersView {
@Inject
lateinit var presenter: MembersPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private val adapter: MembersAdapter =
MembersAdapter { memberUiModel -> presenter.toMemberDetails(memberUiModel) }
private val linearLayoutManager = LinearLayoutManager(context)
......@@ -63,6 +69,10 @@ class MembersFragment : Fragment(), MembersView {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
presenter.loadChatRoomsMembers(chatRoomId)
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Members)
}
}
override fun showMembers(dataSet: List<MemberUiModel>, total: Long) {
......
......@@ -16,9 +16,12 @@ import chat.rocket.android.chatroom.uimodel.BaseUiModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.mentions.presentention.MentionsPresenter
import chat.rocket.android.mentions.presentention.MentionsView
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_mentions.*
import javax.inject.Inject
......@@ -31,6 +34,7 @@ fun newInstance(chatRoomId: String): Fragment {
}
}
internal const val TAG_MENTIONS_FRAGMENT = "MentionsFragment"
private const val BUNDLE_CHAT_ROOM_ID = "chat_room_id"
class MentionsFragment : Fragment(), MentionsView {
......@@ -39,6 +43,8 @@ class MentionsFragment : Fragment(), MentionsView {
private val adapter = ChatRoomAdapter(enableActions = false)
@Inject
lateinit var presenter: MentionsPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -63,6 +69,10 @@ class MentionsFragment : Fragment(), MentionsView {
setupToolbar()
presenter.loadMentions(chatRoomId)
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Mentions)
}
}
override fun showMentions(mentions: List<BaseUiModel<*>>) {
......
package chat.rocket.android.pinnedmessages.ui
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.ChatRoomAdapter
import chat.rocket.android.chatroom.ui.ChatRoomActivity
......@@ -16,9 +16,12 @@ import chat.rocket.android.chatroom.uimodel.BaseUiModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.pinnedmessages.presentation.PinnedMessagesPresenter
import chat.rocket.android.pinnedmessages.presentation.PinnedMessagesView
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_pinned_messages.*
import javax.inject.Inject
......@@ -31,14 +34,16 @@ fun newInstance(chatRoomId: String): Fragment {
}
}
internal const val TAG_PINNED_MESSAGES_FRAGMENT = "PinnedMessagesFragment"
private const val BUNDLE_CHAT_ROOM_ID = "chat_room_id"
class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
private lateinit var chatRoomId: String
private val adapter = ChatRoomAdapter(enableActions = false)
@Inject
lateinit var presenter: PinnedMessagesPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private lateinit var chatRoomId: String
private val adapter = ChatRoomAdapter(enableActions = false)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -63,6 +68,10 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
setupToolbar()
presenter.loadPinnedMessages(chatRoomId)
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.PinnedMessages)
}
}
override fun showPinnedMessages(pinnedMessages: List<BaseUiModel<*>>) {
......
package chat.rocket.android.preferences.di
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.preferences.presentation.PreferencesView
import chat.rocket.android.preferences.ui.PreferencesFragment
import dagger.Module
import dagger.Provides
@Module
class PreferencesFragmentModule {
@Provides
@PerFragment
fun preferencesView(frag: PreferencesFragment): PreferencesView {
return frag
}
}
\ No newline at end of file
package chat.rocket.android.preferences.di
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.preferences.ui.PreferencesFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class PreferencesFragmentProvider {
@ContributesAndroidInjector(modules = [PreferencesFragmentModule::class])
@PerFragment
abstract fun providePreferencesFragment(): PreferencesFragment
}
\ No newline at end of file
package chat.rocket.android.preferences.presentation
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import javax.inject.Inject
class PreferencesPresenter @Inject constructor(
private val view: PreferencesView,
private val analyticsTrackingInteractor: AnalyticsTrackingInteractor
) {
fun loadAnalyticsTrackingInformation() {
view.setupAnalyticsTrackingView(analyticsTrackingInteractor.get())
}
fun enableAnalyticsTracking() {
analyticsTrackingInteractor.save(true)
}
fun disableAnalyticsTracking() {
analyticsTrackingInteractor.save(false)
}
}
\ No newline at end of file
package chat.rocket.android.preferences.presentation
interface PreferencesView {
/**
* Setups the analytics tracking view.
*
* @param isAnalyticsTrackingEnabled Whether the analytics tracking is enabled
*/
fun setupAnalyticsTrackingView(isAnalyticsTrackingEnabled: Boolean)
}
\ No newline at end of file
package chat.rocket.android.preferences.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import chat.rocket.android.BuildConfig
import chat.rocket.android.R
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.preferences.presentation.PreferencesPresenter
import chat.rocket.android.preferences.presentation.PreferencesView
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.fragment_preferences.*
import javax.inject.Inject
internal const val TAG_PREFERENCES_FRAGMENT = "PreferencesFragment"
class PreferencesFragment : Fragment(), PreferencesView {
@Inject
lateinit var presenter: PreferencesPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_preferences, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupListeners()
presenter.loadAnalyticsTrackingInformation()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Preferences)
}
}
override fun setupAnalyticsTrackingView(isAnalyticsTrackingEnabled: Boolean) {
if (BuildConfig.FLAVOR == "foss") {
text_analytics_tracking_description.text =
getString(R.string.msg_not_applicable_since_it_is_a_foss_version)
switch_analytics_tracking.isChecked = false
switch_analytics_tracking.isEnabled = false
return
}
if (isAnalyticsTrackingEnabled) {
text_analytics_tracking_description.text =
getString(R.string.msg_send_analytics_tracking)
} else {
text_analytics_tracking_description.text =
getString(R.string.msg_do_not_send_analytics_tracking)
}
switch_analytics_tracking.isChecked = isAnalyticsTrackingEnabled
}
private fun setupToolbar() {
with((activity as MainActivity).toolbar) {
title = getString(R.string.title_preferences)
setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
setNavigationOnClickListener { activity?.onBackPressed() }
}
}
private fun setupListeners() {
switch_analytics_tracking.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
text_analytics_tracking_description.text =
getString(R.string.msg_send_analytics_tracking)
presenter.enableAnalyticsTracking()
} else {
text_analytics_tracking_description.text =
getString(R.string.msg_do_not_send_analytics_tracking)
presenter.disableAnalyticsTracking()
}
}
}
companion object {
fun newInstance() = PreferencesFragment()
}
}
......@@ -6,7 +6,11 @@ import android.content.Intent
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.core.net.toUri
......@@ -16,6 +20,7 @@ import chat.rocket.android.R
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.profile.presentation.ProfilePresenter
import chat.rocket.android.profile.presentation.ProfileView
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extension.dispatchImageSelection
import chat.rocket.android.util.extension.dispatchTakePicture
......@@ -23,6 +28,8 @@ import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import com.facebook.drawee.backends.pipeline.Fresco
import dagger.android.support.AndroidSupportInjection
import io.reactivex.disposables.CompositeDisposable
......@@ -32,12 +39,16 @@ import kotlinx.android.synthetic.main.fragment_profile.*
import kotlinx.android.synthetic.main.update_avatar_options.*
import javax.inject.Inject
internal const val TAG_PROFILE_FRAGMENT = "ProfileFragment"
private const val REQUEST_CODE_FOR_PERFORM_SAF = 1
private const val REQUEST_CODE_FOR_PERFORM_CAMERA = 2
class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
@Inject
lateinit var presenter: ProfilePresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private var currentName = ""
private var currentUsername = ""
private var currentEmail = ""
......@@ -69,6 +80,10 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
}
presenter.loadUserProfile()
subscribeEditTexts()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Profile)
}
}
override fun onDestroyView() {
......
package chat.rocket.android.server.domain
import javax.inject.Inject
class AnalyticsTrackingInteractor @Inject constructor(val repository: AnalyticsTrackingRepository) {
fun save(isAnalyticsTrackingEnable: Boolean) = repository.save(isAnalyticsTrackingEnable)
fun get(): Boolean = repository.get()
}
\ No newline at end of file
package chat.rocket.android.server.domain
interface AnalyticsTrackingRepository {
fun save(isAnalyticsTrackingEnable: Boolean)
fun get(): Boolean
}
\ No newline at end of file
package chat.rocket.android.server.infraestructure
import android.content.SharedPreferences
import chat.rocket.android.server.domain.AnalyticsTrackingRepository
private const val ANALYTICS_TRACKING_KEY = "ANALYTICS_TRACKING_KEY"
class SharedPrefsAnalyticsTrackingRepository(private val preferences: SharedPreferences) :
AnalyticsTrackingRepository {
override fun save(isAnalyticsTrackingEnable: Boolean) =
preferences.edit().putBoolean(ANALYTICS_TRACKING_KEY, isAnalyticsTrackingEnable).apply()
override fun get() = preferences.getBoolean(ANALYTICS_TRACKING_KEY, true)
}
\ No newline at end of file
......@@ -7,6 +7,7 @@ import chat.rocket.android.server.ui.ChangeServerActivity
import chat.rocket.android.server.ui.INTENT_CHAT_ROOM_ID
class ChangeServerNavigator (internal val activity: ChangeServerActivity) {
fun toServerScreen() {
activity.startActivity(activity.newServerIntent())
activity.finish()
......
......@@ -2,9 +2,16 @@ package chat.rocket.android.server.presentation
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.server.domain.GetAccountInteractor
import chat.rocket.android.server.domain.GetAccountsInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.common.util.ifNull
import javax.inject.Inject
......@@ -16,17 +23,20 @@ class ChangeServerPresenter @Inject constructor(
private val getCurrentServerInteractor: GetCurrentServerInteractor,
private val getAccountInteractor: GetAccountInteractor,
private val getAccountsInteractor: GetAccountsInteractor,
private val analyticsTrackingInteractor: AnalyticsTrackingInteractor,
private val settingsRepository: SettingsRepository,
private val tokenRepository: TokenRepository,
private val localRepository: LocalRepository,
private val connectionManager: ConnectionManagerFactory
) {
fun loadServer(newUrl: String?, chatRoomId: String? = null) {
launchUI(strategy) {
view.showProgress()
var url = newUrl
if (url == null) { // Try to load next server on the list...
val accounts = getAccountsInteractor.get()
val accounts = getAccountsInteractor.get()
if (url == null) {
// Try to load next server on the list...
url = accounts.firstOrNull()?.serverUrl
}
......@@ -56,6 +66,9 @@ class ChangeServerPresenter @Inject constructor(
saveCurrentServerInteractor.save(serverUrl)
view.hideProgress()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logServerSwitch(serverUrl, accounts.size)
}
navigator.toChatRooms(chatRoomId)
}.ifNull {
view.hideProgress()
......
......@@ -11,6 +11,18 @@ import chat.rocket.android.util.extensions.showToast
import dagger.android.AndroidInjection
import javax.inject.Inject
private const val INTENT_SERVER_URL = "INTENT_SERVER_URL"
const val INTENT_CHAT_ROOM_ID = "INTENT_CHAT_ROOM_ID"
fun Context.changeServerIntent(serverUrl: String? = null, chatRoomId: String? = ""): Intent {
return Intent(this, ChangeServerActivity::class.java).apply {
serverUrl?.let { url ->
putExtra(INTENT_SERVER_URL, url)
putExtra(INTENT_CHAT_ROOM_ID, chatRoomId)
}
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
}
class ChangeServerActivity : AppCompatActivity(), ChangeServerView {
@Inject lateinit var presenter: ChangeServerPresenter
......@@ -37,18 +49,3 @@ class ChangeServerActivity : AppCompatActivity(), ChangeServerView {
progress?.dismiss()
}
}
private const val INTENT_SERVER_URL = "INTENT_SERVER_URL"
private const val INTENT_CHAT_ROOM_NAME = "INTENT_CHAT_ROOM_NAME"
private const val INTENT_CHAT_ROOM_TYPE = "INTENT_CHAT_ROOM_TYPE"
const val INTENT_CHAT_ROOM_ID = "INTENT_CHAT_ROOM_ID"
fun Context.changeServerIntent(serverUrl: String? = null, chatRoomId: String? = ""): Intent {
return Intent(this, ChangeServerActivity::class.java).apply {
serverUrl?.let { url ->
putExtra(INTENT_SERVER_URL, url)
putExtra(INTENT_CHAT_ROOM_ID, chatRoomId)
}
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
}
\ No newline at end of file
......@@ -4,7 +4,6 @@ import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import chat.rocket.android.R
import chat.rocket.android.chatrooms.ui.ChatRoomsFragment
import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.util.extensions.textContent
import dagger.android.AndroidInjection
......@@ -23,7 +22,7 @@ class PasswordActivity : AppCompatActivity(), HasSupportFragmentInjector {
setContentView(R.layout.activity_password)
setupToolbar()
addFragment("PasswordFragment")
addFragment(TAG_PASSWORD_FRAGMENT)
}
override fun onBackPressed() {
......@@ -47,6 +46,6 @@ class PasswordActivity : AppCompatActivity(), HasSupportFragmentInjector {
private fun setupToolbar() {
setSupportActionBar(toolbar)
text_change_password.textContent = resources.getString(R.string.title_password)
text_change_password.textContent = resources.getString(R.string.title_change_password)
}
}
package chat.rocket.android.settings.password.ui
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.view.ActionMode
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.settings.password.presentation.PasswordPresenter
import chat.rocket.android.settings.password.presentation.PasswordView
import chat.rocket.android.util.extensions.inflate
import androidx.appcompat.view.ActionMode
import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import dagger.android.support.AndroidSupportInjection
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
......@@ -19,8 +26,13 @@ import io.reactivex.rxkotlin.Observables
import kotlinx.android.synthetic.main.fragment_password.*
import javax.inject.Inject
class PasswordFragment: Fragment(), PasswordView, ActionMode.Callback {
@Inject lateinit var presenter: PasswordPresenter
internal const val TAG_PASSWORD_FRAGMENT = "PasswordFragment"
class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
@Inject
lateinit var presenter: PasswordPresenter
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
private var actionMode: ActionMode? = null
private val disposables = CompositeDisposable()
......@@ -33,12 +45,20 @@ class PasswordFragment: Fragment(), PasswordView, ActionMode.Callback {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = container?.inflate(R.layout.fragment_password)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = container?.inflate(R.layout.fragment_password)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
disposables.add(listenToChanges())
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Password)
}
}
override fun onDestroyView() {
......@@ -98,12 +118,17 @@ class PasswordFragment: Fragment(), PasswordView, ActionMode.Callback {
private fun finishActionMode() = actionMode?.finish()
private fun listenToChanges(): Disposable {
return Observables.combineLatest(text_new_password.asObservable(),
text_confirm_password.asObservable()).subscribe {
return Observables.combineLatest(
text_new_password.asObservable(),
text_confirm_password.asObservable()
).subscribe {
val textPassword = text_new_password.textContent
val textConfirmPassword = text_confirm_password.textContent
if (textPassword.length > 5 && textConfirmPassword.length > 5 && textPassword.equals(textConfirmPassword))
if (textPassword.length > 5 && textConfirmPassword.length > 5 && textPassword.equals(
textConfirmPassword
)
)
startActionMode()
else
finishActionMode()
......
......@@ -2,23 +2,34 @@ package chat.rocket.android.settings.ui
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.about.ui.AboutFragment
import chat.rocket.android.about.ui.TAG_ABOUT_FRAGMENT
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.preferences.ui.PreferencesFragment
import chat.rocket.android.preferences.ui.TAG_PREFERENCES_FRAGMENT
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.settings.password.ui.PasswordActivity
import chat.rocket.android.settings.presentation.SettingsView
import chat.rocket.android.util.extensions.addFragmentBackStack
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.helper.analytics.AnalyticsManager
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import kotlinx.android.synthetic.main.fragment_settings.*
import javax.inject.Inject
import kotlin.reflect.KClass
internal const val TAG_SETTINGS_FRAGMENT = "SettingsFragment"
class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListener {
@Inject
lateinit var analyticsTrackingInteractor: AnalyticsTrackingInteractor
override fun onCreateView(
inflater: LayoutInflater,
......@@ -30,23 +41,35 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen
super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupListView()
if (analyticsTrackingInteractor.get()) {
AnalyticsManager.logScreenView(ScreenViewEvent.Settings)
}
}
override fun onResume() {
// FIXME - gambiarra ahead. will fix when moving to new androidx Navigation
(activity as? MainActivity)?.let {
it.setupNavigationView()
}
(activity as? MainActivity)?.setupNavigationView()
super.onResume()
}
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
when (parent?.getItemAtPosition(position).toString()) {
resources.getString(R.string.title_password) -> {
startNewActivity(PasswordActivity::class)
resources.getString(R.string.title_preferences) -> {
(activity as AppCompatActivity).addFragmentBackStack(
TAG_PREFERENCES_FRAGMENT,
R.id.fragment_container
) {
PreferencesFragment.newInstance()
}
}
resources.getString(R.string.title_change_password) ->
startNewActivity(PasswordActivity::class)
resources.getString(R.string.title_about) -> {
(activity as AppCompatActivity).addFragmentBackStack("AboutFragmnet", R.id.fragment_container){
(activity as AppCompatActivity).addFragmentBackStack(
TAG_ABOUT_FRAGMENT,
R.id.fragment_container
) {
AboutFragment.newInstance()
}
}
......
......@@ -28,7 +28,7 @@
android:textColor="@color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"
tools:text="@string/title_password" />
tools:text="@string/title_change_password" />
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
......
......@@ -6,7 +6,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:context=".members.ui.MemberBottomSheetFragment">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image_bottom_sheet_avatar"
......
......@@ -5,7 +5,7 @@
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".chatinformation.ui.MessageInfoActivity">
tools:context=".chatinformation.ui.MessageInfoFragment">
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/view_loading"
......
......@@ -3,7 +3,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
xmlns:tools="http://schemas.android.com/tools"
tools:context=".settings.password.ui.PasswordFragment">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_new_password"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
tools:context="preferences.ui.PreferencesFragment">
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/view_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:indicatorColor="@color/colorBlack"
app:indicatorName="BallPulseIndicator"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<TextView
android:id="@+id/text_analytics_tracking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/msg_analytics_tracking"
android:textColor="@color/colorPrimaryText"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_analytics_tracking_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/msg_send_analytics_tracking"
android:textColor="@color/colorSecondaryText"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_analytics_tracking" />
<Switch
android:id="@+id/switch_analytics_tracking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
app:layout_constraintBottom_toBottomOf="@+id/text_analytics_tracking_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/text_analytics_tracking" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".settings.ui.SettingsFragment">
<ListView
android:id="@+id/settings_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="@array/settings_actions"/>
</RelativeLayout>
\ No newline at end of file
android:entries="@array/settings_actions" />
</RelativeLayout>
......@@ -11,6 +11,8 @@
<string name="title_profile">Profil</string>
<string name="title_members">Benutzer (%d)</string>
<string name="title_settings">Einstellungen</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">Ändere Passwort</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">Ändere Passwort</string>
<string name="title_update_profile">Update Profil</string>
......@@ -45,6 +47,7 @@
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation -->
<item name="item_password">Ändere Passwort</item>
<item name="item_password">Über</item>
</string-array>
......@@ -143,6 +146,12 @@
<string name="msg_delete_message">Lösche Nachricht</string>
<string name="msg_delete_description">Sind Sie sicher, dass Sie diese Nachricht löschen wollen?</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string> <!-- TODO Add translation -->
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_do_not_send_analytics_tracking">Do not send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_not_applicable_since_it_is_a_foss_version">Not applicable since it is a FOSS version</string> <!-- TODO Add translation -->
<!-- System messages -->
<string name="message_room_name_changed">Raum Namen geändert zu: %1$s von %2$s</string>
<string name="message_user_added_by">Benutzer %1$s hinzugefügt von %2$s</string>
......
......@@ -11,6 +11,8 @@
<string name="title_profile">Perfil</string>
<string name="title_members">Miembros (%d)</string>
<string name="title_settings">Configuraciones</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">Cambia la contraseña</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">Cambia la contraseña</string>
<string name="title_update_profile">Actualización del perfil</string>
......@@ -45,6 +47,7 @@
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation -->
<item name="item_password">Cambia la contraseña</item>
<item name="item_password">Acerca de</item>
</string-array>
......@@ -137,6 +140,12 @@
<string name="msg_member_not_found">Miembro no encontrado</string>
<string name="msg_channel_created_successfully">Canal creado con éxito</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string> <!-- TODO Add translation -->
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_do_not_send_analytics_tracking">Do not send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_not_applicable_since_it_is_a_foss_version">Not applicable since it is a FOSS version</string> <!-- TODO Add translation -->
<!-- System messages -->
<string name="message_room_name_changed">Nombre de la sala cambiado para: %1$s por %2$s</string>
<string name="message_user_added_by">Usuario %1$s añadido por %2$s</string>
......
......@@ -12,6 +12,8 @@
<string name="title_profile">Profil</string>
<string name="title_members">Membres (%d)</string>
<string name="title_settings">Paramètres</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">Changer le mot de passe</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">Changer le mot de passe</string>
<string name="title_update_profile">Update profile</string>
......@@ -47,6 +49,7 @@
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation -->
<item name="item_password">Changer le mot de passe</item>
<item name="item_password">Sur</item>
</string-array>
......@@ -155,6 +158,12 @@
<string name="msg_member_not_found">Member not found</string>
<string name="msg_channel_created_successfully">Channel created successfully</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string> <!-- TODO Add translation -->
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_do_not_send_analytics_tracking">Do not send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_not_applicable_since_it_is_a_foss_version">Not applicable since it is a FOSS version</string> <!-- TODO Add translation -->
<!-- System messages -->
<string name="message_room_name_changed">Le nom de le salle a changé à: %1$s par %2$s</string>
<string name="message_user_added_by">Utilisateur %1$s ajouté par %2$s</string>
......
......@@ -12,6 +12,8 @@
<string name="title_profile">प्रोफाइल</string>
<string name="title_members">सदस्य (%d)</string>
<string name="title_settings">सेटिंग्स</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">पासवर्ड बदलें</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">पासवर्ड बदलें</string>
<string name="title_update_profile">प्रोफ़ाइल अपडेट करें</string>
......@@ -46,6 +48,7 @@
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation -->
<item name="item_password">पासवर्ड बदलें</item>
<item name="item_password">परिचय</item>
</string-array>
......@@ -143,6 +146,12 @@
<string name="msg_member_not_found">सदस्य नहीं मिला</string>
<string name="msg_channel_created_successfully">चैनल सफलतापूर्वक बनाया गया</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string> <!-- TODO Add translation -->
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_do_not_send_analytics_tracking">Do not send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_not_applicable_since_it_is_a_foss_version">Not applicable since it is a FOSS version</string> <!-- TODO Add translation -->
<!-- System messages -->
<string name="message_room_name_changed">%2$s ने रूम का नाम बदलकर %1$s किया</string>
<string name="message_user_added_by">उपयोगकर्ता %1$s द्वारा %2$s को जोड़ा गया</string>
......
......@@ -12,6 +12,8 @@
<string name="title_profile">Perfil</string>
<string name="title_members">Membros (%d)</string>
<string name="title_settings">Configurações</string>
<string name="title_preferences">Preferencias</string>
<string name="title_change_password">Alterar senha</string>
<string name="title_admin_panel">Painel administrativo</string>
<string name="title_password">Alterar senha</string>
<string name="title_update_profile">Editar perfil</string>
......@@ -46,6 +48,7 @@
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferencias</item>
<item name="item_password">Alterar senha</item>
<item name="item_password">Sobre</item>
</string-array>
......@@ -143,6 +146,12 @@
<string name="msg_member_not_found">Membro não encontrado</string>
<string name="msg_channel_created_successfully">Chat criado com sucesso</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Rastreamento de análises</string>
<string name="msg_send_analytics_tracking">Envie estatísticas anônimas para ajudar a melhorar este app</string>
<string name="msg_do_not_send_analytics_tracking">Não envie estatísticas anônimas para ajudar a melhorar este app</string>
<string name="msg_not_applicable_since_it_is_a_foss_version">Not aplicável devido a versão do aplicativo ser FOSS</string> <!-- TODO Add translation -->
<!-- System messages -->
<string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string>
<string name="message_user_added_by">Usuário %1$s adicionado por %2$s</string>
......
......@@ -12,6 +12,8 @@
<string name="title_profile">Профиль</string>
<string name="title_members">Пользователи (%d)</string>
<string name="title_settings">Настройки</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">Изменить пароль</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">Изменить пароль</string>
<string name="title_update_profile">Обновить профиль</string>
......@@ -46,6 +48,7 @@
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation -->
<item name="item_password">Изменить пароль</item>
<item name="item_password">О программе</item>
</string-array>
......@@ -140,6 +143,12 @@
<string name="msg_member_not_found">Пользователь не найден</string>
<string name="msg_channel_created_successfully">Канал создан успешно</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string> <!-- TODO Add translation -->
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_do_not_send_analytics_tracking">Do not send anonymous statics to help improving this app</string> <!-- TODO Add translation -->
<string name="msg_not_applicable_since_it_is_a_foss_version">Not applicable since it is a FOSS version</string> <!-- TODO Add translation -->
<!-- System messages -->
<string name="message_room_name_changed">%2$s изменил название канала на %1$s</string>
<string name="message_user_added_by">Пользователь %1$s добавлен пользователем %2$s</string>
......
......@@ -13,6 +13,8 @@
<string name="title_profile">Profile</string>
<string name="title_members">Members (%d)</string>
<string name="title_settings">Settings</string>
<string name="title_preferences">Preferences</string>
<string name="title_change_password">Change Password</string>
<string name="title_admin_panel">Admin panel</string>
<string name="title_password">Change Password</string>
<string name="title_update_profile">Update profile</string>
......@@ -47,6 +49,7 @@
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferences</item>
<item name="item_password">Change Password</item>
<item name="item_password">About</item>
</string-array>
......@@ -145,6 +148,12 @@
<string name="msg_message_copied">Message copied</string>
<string name="msg_delete_message">Delete Message</string>
<string name="msg_delete_description">Are you sure you want to delete this message</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string>
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string>
<string name="msg_do_not_send_analytics_tracking">Do not send anonymous statics to help improving this app</string>
<string name="msg_not_applicable_since_it_is_a_foss_version">Not applicable since it is a FOSS version</string>
<!-- System messages -->
<string name="message_room_name_changed">Room name changed to: %1$s by %2$s</string>
......
......@@ -20,10 +20,8 @@ fun Activity.requestStoredCredentials(): Pair<String, String>? {
fun getCredentials(data: Intent): Pair<String, String>? {
val credentials: Credential = data.getParcelableExtra(Credential.EXTRA_KEY)
return credentials?.let { cred ->
cred.password?.let {
Pair(cred.id, it)
}
return credentials.password?.let {
Pair(credentials.id, it)
}
}
......
......@@ -7,12 +7,23 @@ import com.crashlytics.android.core.CrashlyticsCore
import android.content.Context
import chat.rocket.android.app.RocketChatApplication
import chat.rocket.android.infrastructure.installCrashlyticsWrapper
import com.crashlytics.android.answers.Answers
fun setupCrashlytics(context: Context) {
fun setupFabric(context: Context) {
val core = CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()
Fabric.with(context, Crashlytics.Builder().core(core).build())
Fabric.with(
context,
Crashlytics.Builder()
.core(core) // For Crashlytics
.answers(Answers()) // For Answers
.build()
)
installCrashlyticsWrapper(context as RocketChatApplication,
context.getCurrentServerInteractor, context.settingsInteractor,
context.accountRepository, context.localRepository)
}
\ No newline at end of file
installCrashlyticsWrapper(
context as RocketChatApplication,
context.getCurrentServerInteractor,
context.settingsInteractor,
context.accountRepository,
context.localRepository
)
}
package chat.rocket.android.util
import chat.rocket.android.R
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.main.presentation.MainPresenter
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
......
......@@ -10,7 +10,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.0-alpha05'
classpath 'com.android.tools.build:gradle:3.3.0-alpha06'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath 'com.google.gms:google-services:4.0.2'
......
......@@ -9,7 +9,7 @@ ext {
dokka : '0.9.16',
// For app
kotlin : '1.2.51',
kotlin : '1.2.61',
coroutine : '0.24.0',
appCompat : '1.0.0-beta01',
......@@ -20,7 +20,8 @@ ext {
androidKtx : '1.0.0-beta01',
dagger : '2.16',
firebase : '15.0.0',
firebaseCloudMessage : '17.1.0',
firebaseAnalytics : '16.0.1',
playServices : '15.0.1',
exoPlayer : '2.8.2',
flexbox : '1.0.0',
......@@ -74,8 +75,6 @@ ext {
daggerSupport : "com.google.dagger:dagger-android-support:${versions.dagger}",
daggerProcessor : "com.google.dagger:dagger-compiler:${versions.dagger}",
daggerAndroidApt : "com.google.dagger:dagger-android-processor:${versions.dagger}",
fcm : "com.google.firebase:firebase-messaging:${versions.firebase}",
playServicesAuth : "com.google.android.gms:play-services-auth:${versions.playServices}",
exoPlayer : "com.google.android.exoplayer:exoplayer:${versions.exoPlayer}",
flexbox : "com.google.android:flexbox:${versions.flexbox}",
material : "com.google.android.material:material:${versions.material}",
......@@ -112,6 +111,11 @@ ext {
aVLoadingIndicatorView: "com.wang.avi:library:${versions.aVLoadingIndicatorView}",
// Proprietary libraries
fcm : "com.google.firebase:firebase-messaging:${versions.firebaseCloudMessage}",
firebaseAnalytics : "com.google.firebase:firebase-core:${versions.firebaseAnalytics}",
playServicesAuth : "com.google.android.gms:play-services-auth:${versions.playServices}",
// For wearable
wearable : "com.google.android.support:wearable:${versions.wear}",
playServicesWearable : "com.google.android.gms:play-services-wearable:${versions.playServicesWearable}",
......
......@@ -19,14 +19,36 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// Since we are using the util module here, we need to declare the same flavorDimensions and
// productFlavors from there.
flavorDimensions "type"
productFlavors {
// includes proprietary libs
play {
dimension "type"
}
// only foss
foss {
dimension "type"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':util')
implementation project(':core')
implementation project(':util')
implementation libraries.kotlin
implementation libraries.coroutines
......
......@@ -17,6 +17,25 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
flavorDimensions "type"
productFlavors {
// includes proprietary libs
play {
dimension "type"
}
// only foss
foss {
dimension "type"
}
}
}
......@@ -36,4 +55,9 @@ dependencies {
// TODO This is a dependency from the core module, but the util module are unable to get that dependencies. Check why it is occurring since transitive is enable by default
implementation libraries.lifecycleExtensions
kapt libraries.lifecycleCompiler
// Proprietary libraries
playImplementation('com.crashlytics.sdk.android:answers:1.4.2@aar') {
transitive = true
}
}
\ No newline at end of file
package chat.rocket.android.util.helper.analytics
import chat.rocket.android.util.helper.analytics.event.AuthenticationEvent
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.android.util.helper.analytics.event.SubscriptionTypeEvent
object AnalyticsManager : 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
}
}
package chat.rocket.android.util.helper.analytics
import chat.rocket.android.util.helper.analytics.event.AuthenticationEvent
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.android.util.helper.analytics.event.SubscriptionTypeEvent
interface Analytics {
/**
* Logs the login event.
*
* @param event The [AuthenticationEvent] used to log in.
* @param loginSucceeded True if successful logged in, false otherwise.
*/
fun logLogin(event: AuthenticationEvent, loginSucceeded: Boolean)
/**
* Logs the sign up event.
*
* @param event The [AuthenticationEvent] used to sign up.
* @param signUpSucceeded True if successful signed up, false otherwise.
*/
fun logSignUp(event: AuthenticationEvent, signUpSucceeded: Boolean)
/**
* Logs the screen view event.
*
* @param event The [ScreenViewEvent] to log.
*/
fun logScreenView(event: ScreenViewEvent)
/**
* Logs the message sent event.
*
* @param event The [SubscriptionTypeEvent] to log.
* @param serverUrl The server URL to log.
*/
fun logMessageSent(event: SubscriptionTypeEvent, serverUrl: String)
/**
* Logs the media upload event.
*
* @param event The [SubscriptionTypeEvent] to log.
* @param mimeType The mime type of the media uploaded to log.
*/
fun logMediaUploaded(event: SubscriptionTypeEvent, mimeType: String)
/**
* Logs the reaction event.
*
* @param event The [SubscriptionTypeEvent] to log.
*/
fun logReaction(event: SubscriptionTypeEvent)
/**
* Logs the server switch event.
*
* @param serverUrl The server URL to log.
* @param serverCount The number of server(s) the use own.
*/
fun logServerSwitch(serverUrl: String, serverCount: Int)
}
package chat.rocket.android.util.helper.analytics.event
sealed class AuthenticationEvent(val methodName: String) {
object AuthenticationWithUserAndPassword : AuthenticationEvent("User and password")
object AuthenticationWithCas : AuthenticationEvent("CAS")
object AuthenticationWithSaml : AuthenticationEvent("SAML")
object AuthenticationWithOauth : AuthenticationEvent("Oauth")
object AuthenticationWithDeeplink : AuthenticationEvent("Deep link")
}
package chat.rocket.android.util.helper.analytics.event
sealed class ScreenViewEvent(val screenName: String) {
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")
object MessageInfo : ScreenViewEvent("MessageInfoFragment")
object Password : ScreenViewEvent("PasswordFragment")
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")
}
\ No newline at end of file
package chat.rocket.android.util.helper.analytics.event
sealed class SubscriptionTypeEvent(val subscriptionTypeName: String) {
object DirectMessage : SubscriptionTypeEvent("Direct Message")
object Channel : SubscriptionTypeEvent("Channel")
object Group : SubscriptionTypeEvent("Group")
}
\ No newline at end of file
package chat.rocket.android.util.helper.analytics
import chat.rocket.android.util.helper.analytics.event.AuthenticationEvent
import chat.rocket.android.util.helper.analytics.event.ScreenViewEvent
import chat.rocket.android.util.helper.analytics.event.SubscriptionTypeEvent
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.CustomEvent
import com.crashlytics.android.answers.LoginEvent
import com.crashlytics.android.answers.SignUpEvent
// TODO inject the and analyticsTrackingInteractor and GetCurrentServerInteractor
object AnalyticsManager : Analytics {
override fun logLogin(event: AuthenticationEvent, loginSucceeded: Boolean) =
Answers.getInstance()
.logLogin(
LoginEvent()
.putMethod(event.methodName)
.putSuccess(loginSucceeded)
)
override fun logSignUp(event: AuthenticationEvent, signUpSucceeded: Boolean) =
Answers.getInstance()
.logSignUp(
SignUpEvent()
.putMethod(event.methodName)
.putSuccess(signUpSucceeded)
)
override fun logScreenView(event: ScreenViewEvent) =
Answers.getInstance()
.logCustom(CustomEvent("screen_view").putCustomAttribute("screen", event.screenName))
override fun logMessageSent(event: SubscriptionTypeEvent, serverUrl: String) =
Answers.getInstance()
.logCustom(
CustomEvent("message_sent")
.putCustomAttribute("subscription_type", event.subscriptionTypeName)
.putCustomAttribute("server", serverUrl)
)
override fun logMediaUploaded(event: SubscriptionTypeEvent, mimeType: String) =
Answers.getInstance()
.logCustom(
CustomEvent("media_upload")
.putCustomAttribute("subscription_type", event.subscriptionTypeName)
.putCustomAttribute("media_type", mimeType)
)
override fun logReaction(event: SubscriptionTypeEvent) =
Answers.getInstance()
.logCustom(
CustomEvent("reaction")
.putCustomAttribute("subscription_type", event.subscriptionTypeName)
)
override fun logServerSwitch(serverUrl: String, serverCount: Int) =
Answers.getInstance()
.logCustom(
CustomEvent("server_switch")
.putCustomAttribute("server_url", serverUrl)
.putCustomAttribute("server_count", serverCount)
)
}
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