Unverified Commit 38c960d8 authored by Ergashev Adizbek's avatar Ergashev Adizbek Committed by GitHub

Merge branch 'develop' into swipe-to-reply

parents 3b355afd 521f0a8b
...@@ -18,8 +18,8 @@ android { ...@@ -18,8 +18,8 @@ android {
applicationId "chat.rocket.android" applicationId "chat.rocket.android"
minSdkVersion versions.minSdk minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk
versionCode 2060 versionCode 2061
versionName "3.3.0" versionName "3.4.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
......
...@@ -27,4 +27,5 @@ sealed class ScreenViewEvent(val screenName: String) { ...@@ -27,4 +27,5 @@ sealed class ScreenViewEvent(val screenName: String) {
object Preferences : ScreenViewEvent("PreferencesFragment") object Preferences : ScreenViewEvent("PreferencesFragment")
object Profile : ScreenViewEvent("ProfileFragment") object Profile : ScreenViewEvent("ProfileFragment")
object Settings : ScreenViewEvent("SettingsFragment") object Settings : ScreenViewEvent("SettingsFragment")
object Directory : ScreenViewEvent("DirectoryFragment")
} }
...@@ -4,7 +4,7 @@ import androidx.lifecycle.Lifecycle ...@@ -4,7 +4,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.OnLifecycleEvent
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
......
...@@ -24,7 +24,7 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor ...@@ -24,7 +24,7 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.SITE_URL import chat.rocket.android.server.domain.SITE_URL
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.android.util.setupFabric import chat.rocket.android.util.setupFabric
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
......
package chat.rocket.android.authentication.infraestructure package chat.rocket.android.authentication.infrastructure
import chat.rocket.android.authentication.domain.model.TokenModel import chat.rocket.android.authentication.domain.model.TokenModel
import chat.rocket.android.dagger.scope.PerActivity import chat.rocket.android.dagger.scope.PerActivity
......
package chat.rocket.android.authentication.infraestructure package chat.rocket.android.authentication.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.core.content.edit import androidx.core.content.edit
......
...@@ -16,7 +16,7 @@ import chat.rocket.android.server.domain.isLdapAuthenticationEnabled ...@@ -16,7 +16,7 @@ import chat.rocket.android.server.domain.isLdapAuthenticationEnabled
import chat.rocket.android.server.domain.isPasswordResetEnabled import chat.rocket.android.server.domain.isPasswordResetEnabled
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.isEmail import chat.rocket.android.util.extensions.isEmail
......
...@@ -15,7 +15,7 @@ import chat.rocket.android.server.domain.TokenRepository ...@@ -15,7 +15,7 @@ import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.serverLogoUrl import chat.rocket.android.util.extensions.serverLogoUrl
......
...@@ -25,18 +25,18 @@ interface LoginOptionsView : LoadingView, MessageView { ...@@ -25,18 +25,18 @@ interface LoginOptionsView : LoadingView, MessageView {
fun setupFacebookButtonListener(facebookOauthUrl: String, state: String) fun setupFacebookButtonListener(facebookOauthUrl: String, state: String)
/** /**
* Shows the "login by Github" view if it is enabled by the server settings. * Shows the "login by GitHub" view if it is enabled by the server settings.
* *
* REMARK: We must set up the Github button listener before enabling it * REMARK: We must set up the GitHub button listener before enabling it
* [setupGithubButtonListener]. * [setupGithubButtonListener].
* @see [showAccountsView] * @see [showAccountsView]
*/ */
fun enableLoginByGithub() fun enableLoginByGithub()
/** /**
* Setups the Github button. * Setups the GitHub button.
* *
* @param githubUrl The Github OAuth URL to authenticate with. * @param githubUrl The GitHub OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later * @param state A random string generated by the app, which you'll verify later
* (to protect against forgery attacks). * (to protect against forgery attacks).
*/ */
...@@ -61,36 +61,36 @@ interface LoginOptionsView : LoadingView, MessageView { ...@@ -61,36 +61,36 @@ interface LoginOptionsView : LoadingView, MessageView {
fun setupGoogleButtonListener(googleUrl: String, state: String) fun setupGoogleButtonListener(googleUrl: String, state: String)
/** /**
* Shows the "login by Linkedin" view if it is enabled by the server settings. * Shows the "login by LinkedIn" view if it is enabled by the server settings.
* *
* REMARK: We must set up the Linkedin button listener before enabling it * REMARK: We must set up the LinkedIn button listener before enabling it
* [setupLinkedinButtonListener]. * [setupLinkedinButtonListener].
* @see [showAccountsView] * @see [showAccountsView]
*/ */
fun enableLoginByLinkedin() fun enableLoginByLinkedin()
/** /**
* Setups the Linkedin button. * Setups the LinkedIn button.
* *
* @param linkedinUrl The Linkedin OAuth URL to authenticate with. * @param linkedinUrl The LinkedIn OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later * @param state A random string generated by the app, which you'll verify later
* (to protect against forgery attacks). * (to protect against forgery attacks).
*/ */
fun setupLinkedinButtonListener(linkedinUrl: String, state: String) fun setupLinkedinButtonListener(linkedinUrl: String, state: String)
/** /**
* Shows the "login by Gitlab" view if it is enabled by the server settings. * Shows the "login by GitLab" view if it is enabled by the server settings.
* *
* REMARK: We must set up the Gitlab button listener before enabling it * REMARK: We must set up the GitLab button listener before enabling it
* [setupGitlabButtonListener]. * [setupGitlabButtonListener].
* @see [showAccountsView] * @see [showAccountsView]
*/ */
fun enableLoginByGitlab() fun enableLoginByGitlab()
/** /**
* Setups the Gitlab button. * Setups the GitLab button.
* *
* @param gitlabUrl The Gitlab OAuth URL to authenticate with. * @param gitlabUrl The GitLab OAuth URL to authenticate with.
* @param state A random string generated by the app, which you'll verify later * @param state A random string generated by the app, which you'll verify later
* (to protect against forgery attacks). * (to protect against forgery attacks).
*/ */
...@@ -99,7 +99,7 @@ interface LoginOptionsView : LoadingView, MessageView { ...@@ -99,7 +99,7 @@ interface LoginOptionsView : LoadingView, MessageView {
/** /**
* Shows the "login by WordPress" view if it is enabled by the server settings. * Shows the "login by WordPress" view if it is enabled by the server settings.
* *
* REMARK: We must set up the Gitlab button listener before enabling it [setupWordpressButtonListener]. * REMARK: We must set up the GitLab button listener before enabling it [setupWordpressButtonListener].
*/ */
fun enableLoginByWordpress() fun enableLoginByWordpress()
......
package chat.rocket.android.authentication.loginoptions.ui package chat.rocket.android.authentication.loginoptions.ui
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.graphics.PorterDuff import android.graphics.PorterDuff
...@@ -7,10 +10,13 @@ import android.os.Bundle ...@@ -7,10 +10,13 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.widget.Button import android.widget.Button
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.appcompat.view.ContextThemeWrapper import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.marginTop
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
...@@ -28,6 +34,7 @@ import chat.rocket.android.webview.sso.ui.ssoWebViewIntent ...@@ -28,6 +34,7 @@ import chat.rocket.android.webview.sso.ui.ssoWebViewIntent
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.app_bar.* import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.fragment_authentication_login_options.* import kotlinx.android.synthetic.main.fragment_authentication_login_options.*
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
private const val SERVER_NAME = "server_name" private const val SERVER_NAME = "server_name"
...@@ -61,6 +68,8 @@ internal const val REQUEST_CODE_FOR_OAUTH = 1 ...@@ -61,6 +68,8 @@ internal const val REQUEST_CODE_FOR_OAUTH = 1
internal const val REQUEST_CODE_FOR_CAS = 2 internal const val REQUEST_CODE_FOR_CAS = 2
internal const val REQUEST_CODE_FOR_SAML = 3 internal const val REQUEST_CODE_FOR_SAML = 3
private const val DEFAULT_ANIMATION_DURATION = 400L
fun newInstance( fun newInstance(
serverName: String, serverName: String,
state: String? = null, state: String? = null,
...@@ -238,7 +247,6 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView { ...@@ -238,7 +247,6 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
enableLoginByLinkedin() enableLoginByLinkedin()
} }
if (gitlabOauthUrl != null && state != null) { if (gitlabOauthUrl != null && state != null) {
setupGitlabButtonListener(gitlabOauthUrl.toString(), state.toString()) setupGitlabButtonListener(gitlabOauthUrl.toString(), state.toString())
enableLoginByGitlab() enableLoginByGitlab()
...@@ -390,11 +398,11 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView { ...@@ -390,11 +398,11 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
var isAccountsCollapsed = true var isAccountsCollapsed = true
button_expand_collapse_accounts.setOnClickListener { button_expand_collapse_accounts.setOnClickListener {
isAccountsCollapsed = if (isAccountsCollapsed) { isAccountsCollapsed = if (isAccountsCollapsed) {
button_expand_collapse_accounts.rotateBy(180F, 400) button_expand_collapse_accounts.rotateBy(180F, DEFAULT_ANIMATION_DURATION)
expandAccountsView() expandAccountsView()
false false
} else { } else {
button_expand_collapse_accounts.rotateBy(180F, 400) button_expand_collapse_accounts.rotateBy(180F, DEFAULT_ANIMATION_DURATION)
collapseAccountsView() collapseAccountsView()
true true
} }
...@@ -532,17 +540,73 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView { ...@@ -532,17 +540,73 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
} }
private fun expandAccountsView() { private fun expandAccountsView() {
(0..accounts_container.childCount) val buttons = (0..accounts_container.childCount)
.mapNotNull { accounts_container.getChildAt(it) as? Button } .mapNotNull { accounts_container.getChildAt(it) as? Button }
.filter { it.isClickable && !it.isVisible } .filter { it.isClickable && !it.isVisible }
.forEach { it.isVisible = true } val optionHeight = accounts_container.getChildAt(1).height +
accounts_container.getChildAt(1).marginTop
val collapsedHeight = accounts_container.height
val expandedHeight = collapsedHeight + optionHeight * buttons.size
with(ValueAnimator.ofInt(collapsedHeight, expandedHeight)) {
addUpdateListener {
val params = accounts_container.layoutParams
params.height = animatedValue as Int
accounts_container.layoutParams = params
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animator: Animator) {
buttons.forEach {
it.isVisible = true
val anim = AlphaAnimation(0.0f, 1.0f)
anim.duration = DEFAULT_ANIMATION_DURATION
it.startAnimation(anim)
}
}
})
setDuration(DEFAULT_ANIMATION_DURATION).start()
}
} }
private fun collapseAccountsView() { private fun collapseAccountsView() {
(0..accounts_container.childCount) val buttons = (0..accounts_container.childCount)
.mapNotNull { accounts_container.getChildAt(it) as? Button } .mapNotNull { accounts_container.getChildAt(it) as? Button }
.filter { it.isClickable && it.isVisible } .filter { it.isClickable && it.isVisible }
.drop(3) .drop(3)
.forEach { it.isVisible = false } val optionHeight = accounts_container.getChildAt(1).height +
accounts_container.getChildAt(1).marginTop
val expandedHeight = accounts_container.height
val collapsedHeight = expandedHeight - optionHeight * buttons.size
with(ValueAnimator.ofInt(expandedHeight, collapsedHeight)) {
addUpdateListener {
val params = accounts_container.layoutParams
params.height = animatedValue as Int
accounts_container.layoutParams = params
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animator: Animator) {
buttons.forEach {
val anim = AlphaAnimation(1.0f, 0.0f)
anim.duration = DEFAULT_ANIMATION_DURATION
anim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
Timber.d("Animation starts: $animation")
}
override fun onAnimationEnd(animation: Animation) {
it.isVisible = false
}
override fun onAnimationRepeat(animation: Animation) {
Timber.d("Animation repeats: $animation")
}
})
it.startAnimation(anim)
}
}
})
setDuration(DEFAULT_ANIMATION_DURATION).start()
}
} }
} }
...@@ -7,7 +7,7 @@ import chat.rocket.android.server.domain.GetAccountsInteractor ...@@ -7,7 +7,7 @@ import chat.rocket.android.server.domain.GetAccountsInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.RefreshSettingsInteractor import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.domain.SaveConnectingServerInteractor import chat.rocket.android.server.domain.SaveConnectingServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.server.presentation.CheckServerPresenter import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
......
...@@ -13,7 +13,7 @@ import chat.rocket.android.server.domain.TokenRepository ...@@ -13,7 +13,7 @@ import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.serverLogoUrl import chat.rocket.android.util.extensions.serverLogoUrl
......
...@@ -3,7 +3,7 @@ package chat.rocket.android.authentication.resetpassword.presentation ...@@ -3,7 +3,7 @@ package chat.rocket.android.authentication.resetpassword.presentation
import chat.rocket.android.authentication.presentation.AuthenticationNavigator import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.GetConnectingServerInteractor import chat.rocket.android.server.domain.GetConnectingServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
......
...@@ -8,7 +8,7 @@ import chat.rocket.android.server.domain.GetAccountsInteractor ...@@ -8,7 +8,7 @@ import chat.rocket.android.server.domain.GetAccountsInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.RefreshSettingsInteractor import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.domain.SaveConnectingServerInteractor import chat.rocket.android.server.domain.SaveConnectingServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.server.presentation.CheckServerPresenter import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.isValidUrl import chat.rocket.android.util.extensions.isValidUrl
......
...@@ -13,7 +13,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor ...@@ -13,7 +13,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.privacyPolicyUrl import chat.rocket.android.util.extensions.privacyPolicyUrl
......
...@@ -14,7 +14,7 @@ import chat.rocket.android.server.domain.TokenRepository ...@@ -14,7 +14,7 @@ import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.isEmail import chat.rocket.android.util.extensions.isEmail
......
...@@ -4,7 +4,7 @@ import chat.rocket.android.chatdetails.domain.ChatDetails ...@@ -4,7 +4,7 @@ import chat.rocket.android.chatdetails.domain.ChatDetails
import chat.rocket.android.chatroom.presentation.ChatRoomNavigator import chat.rocket.android.chatroom.presentation.ChatRoomNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
......
...@@ -3,7 +3,7 @@ package chat.rocket.android.chatinformation.presentation ...@@ -3,7 +3,7 @@ package chat.rocket.android.chatinformation.presentation
import chat.rocket.android.chatroom.uimodel.UiModelMapper import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
......
...@@ -33,8 +33,8 @@ import chat.rocket.android.server.domain.UsersRepository ...@@ -33,8 +33,8 @@ import chat.rocket.android.server.domain.UsersRepository
import chat.rocket.android.server.domain.uploadMaxFileSize import chat.rocket.android.server.domain.uploadMaxFileSize
import chat.rocket.android.server.domain.uploadMimeTypeFilter import chat.rocket.android.server.domain.uploadMimeTypeFilter
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.state import chat.rocket.android.server.infrastructure.state
import chat.rocket.android.util.extension.getByteArray import chat.rocket.android.util.extension.getByteArray
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
......
...@@ -4,9 +4,9 @@ import android.app.job.JobParameters ...@@ -4,9 +4,9 @@ import android.app.job.JobParameters
import android.app.job.JobService import android.app.job.JobService
import chat.rocket.android.db.DatabaseManagerFactory import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.server.domain.GetAccountsInteractor import chat.rocket.android.server.domain.GetAccountsInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.DatabaseMessageMapper import chat.rocket.android.server.infrastructure.DatabaseMessageMapper
import chat.rocket.android.server.infraestructure.DatabaseMessagesRepository import chat.rocket.android.server.infrastructure.DatabaseMessagesRepository
import chat.rocket.core.internal.rest.sendMessage import chat.rocket.core.internal.rest.sendMessage
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
import dagger.android.AndroidInjection import dagger.android.AndroidInjection
......
...@@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment ...@@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.presentation.ChatRoomNavigator import chat.rocket.android.chatroom.presentation.ChatRoomNavigator
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extensions.addFragment import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.util.extensions.textContent import chat.rocket.android.util.extensions.textContent
import dagger.android.AndroidInjection import dagger.android.AndroidInjection
......
...@@ -74,6 +74,7 @@ import chat.rocket.android.helper.AndroidPermissionsHelper.hasCameraPermission ...@@ -74,6 +74,7 @@ import chat.rocket.android.helper.AndroidPermissionsHelper.hasCameraPermission
import chat.rocket.android.helper.AndroidPermissionsHelper.hasWriteExternalStoragePermission import chat.rocket.android.helper.AndroidPermissionsHelper.hasWriteExternalStoragePermission
import chat.rocket.android.util.extension.asObservable import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extension.createImageFile import chat.rocket.android.util.extension.createImageFile
import chat.rocket.android.util.extension.orFalse
import chat.rocket.android.util.extensions.circularRevealOrUnreveal import chat.rocket.android.util.extensions.circularRevealOrUnreveal
import chat.rocket.android.util.extensions.clearLightStatusBar import chat.rocket.android.util.extensions.clearLightStatusBar
import chat.rocket.android.util.extensions.fadeIn import chat.rocket.android.util.extensions.fadeIn
...@@ -150,14 +151,10 @@ private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message" ...@@ -150,14 +151,10 @@ private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message"
class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener, class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener,
ChatRoomAdapter.OnActionSelected, Drawable.Callback { ChatRoomAdapter.OnActionSelected, Drawable.Callback {
@Inject @Inject lateinit var presenter: ChatRoomPresenter
lateinit var presenter: ChatRoomPresenter @Inject lateinit var parser: MessageParser
@Inject @Inject lateinit var analyticsManager: AnalyticsManager
lateinit var parser: MessageParser @Inject lateinit var navigator: ChatRoomNavigator
@Inject
lateinit var analyticsManager: AnalyticsManager
@Inject
lateinit var navigator: ChatRoomNavigator
private lateinit var adapter: ChatRoomAdapter private lateinit var adapter: ChatRoomAdapter
internal lateinit var chatRoomId: String internal lateinit var chatRoomId: String
private lateinit var chatRoomName: String private lateinit var chatRoomName: String
...@@ -470,6 +467,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -470,6 +467,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
setupToolbar(roomUiModel.name.toString()) setupToolbar(roomUiModel.name.toString())
setupMessageComposer(roomUiModel) setupMessageComposer(roomUiModel)
isBroadcastChannel = roomUiModel.broadcast isBroadcastChannel = roomUiModel.broadcast
isFavorite = roomUiModel.favorite.orFalse()
if (isBroadcastChannel && !roomUiModel.canModerate) { if (isBroadcastChannel && !roomUiModel.canModerate) {
disableMenu = true disableMenu = true
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
...@@ -606,45 +604,31 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -606,45 +604,31 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
override fun showMessage(message: String) { override fun showMessage(message: String) {
ui { ui { showToast(message) }
showToast(message)
}
} }
override fun showMessage(resId: Int) { override fun showMessage(resId: Int) {
ui { ui { showToast(resId) }
showToast(resId)
}
} }
override fun showGenericErrorMessage() { override fun showGenericErrorMessage() {
ui { ui { showMessage(getString(R.string.msg_generic_error)) }
showMessage(getString(R.string.msg_generic_error))
}
} }
override fun populatePeopleSuggestions(members: List<PeopleSuggestionUiModel>) { override fun populatePeopleSuggestions(members: List<PeopleSuggestionUiModel>) {
ui { ui { suggestions_view.addItems("@", members) }
suggestions_view.addItems("@", members)
}
} }
override fun populateRoomSuggestions(chatRooms: List<ChatRoomSuggestionUiModel>) { override fun populateRoomSuggestions(chatRooms: List<ChatRoomSuggestionUiModel>) {
ui { ui { suggestions_view.addItems("#", chatRooms) }
suggestions_view.addItems("#", chatRooms)
}
} }
override fun populateCommandSuggestions(commands: List<CommandSuggestionUiModel>) { override fun populateCommandSuggestions(commands: List<CommandSuggestionUiModel>) {
ui { ui { suggestions_view.addItems("/", commands) }
suggestions_view.addItems("/", commands)
}
} }
override fun populateEmojiSuggestions(emojis: List<EmojiSuggestionUiModel>) { override fun populateEmojiSuggestions(emojis: List<EmojiSuggestionUiModel>) {
ui { ui { suggestions_view.addItems(":", emojis) }
suggestions_view.addItems(":", emojis)
}
} }
override fun copyToClipboard(message: String) { override fun copyToClipboard(message: String) {
......
...@@ -30,7 +30,7 @@ import chat.rocket.android.server.domain.baseUrl ...@@ -30,7 +30,7 @@ import chat.rocket.android.server.domain.baseUrl
import chat.rocket.android.server.domain.messageReadReceiptEnabled import chat.rocket.android.server.domain.messageReadReceiptEnabled
import chat.rocket.android.server.domain.messageReadReceiptStoreUsers import chat.rocket.android.server.domain.messageReadReceiptStoreUsers
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.isImage import chat.rocket.android.util.extension.isImage
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.ifNotNullNorEmpty import chat.rocket.android.util.extensions.ifNotNullNorEmpty
......
...@@ -167,7 +167,7 @@ class RoomUiModelMapper( ...@@ -167,7 +167,7 @@ class RoomUiModelMapper(
private fun roomType(type: String): String = with(context.resources) { private fun roomType(type: String): String = with(context.resources) {
when (type) { when (type) {
RoomType.CHANNEL -> getString(R.string.header_channel) RoomType.CHANNEL -> getString(R.string.msg_channels)
RoomType.PRIVATE_GROUP -> getString(R.string.header_private_groups) RoomType.PRIVATE_GROUP -> getString(R.string.header_private_groups)
RoomType.DIRECT_MESSAGE -> getString(R.string.header_direct_messages) RoomType.DIRECT_MESSAGE -> getString(R.string.header_direct_messages)
RoomType.LIVECHAT -> getString(R.string.header_live_chats) RoomType.LIVECHAT -> getString(R.string.header_live_chats)
......
...@@ -15,9 +15,9 @@ import chat.rocket.android.server.domain.PermissionsInteractor ...@@ -15,9 +15,9 @@ import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infrastructure.ConnectionManager
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
......
...@@ -13,7 +13,7 @@ import chat.rocket.android.server.domain.SettingsRepository ...@@ -13,7 +13,7 @@ import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.SortingAndGroupingInteractor import chat.rocket.android.server.domain.SortingAndGroupingInteractor
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.domain.useSpecialCharsOnRoom import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infrastructure.ConnectionManager
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryDB import chat.rocket.android.util.retryDB
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
...@@ -50,6 +50,8 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -50,6 +50,8 @@ class ChatRoomsPresenter @Inject constructor(
fun toSettings() = navigator.toSettings() fun toSettings() = navigator.toSettings()
fun toDirectory() = navigator.toDirectory()
fun getCurrentServerName() = view.setupToolbar(currentServer) fun getCurrentServerName() = view.setupToolbar(currentServer)
fun getSortingAndGroupingPreferences() { fun getSortingAndGroupingPreferences() {
......
...@@ -9,6 +9,7 @@ import android.view.View ...@@ -9,6 +9,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
...@@ -44,7 +45,6 @@ internal const val TAG_CHAT_ROOMS_FRAGMENT = "ChatRoomsFragment" ...@@ -44,7 +45,6 @@ internal const val TAG_CHAT_ROOMS_FRAGMENT = "ChatRoomsFragment"
private const val BUNDLE_CHAT_ROOM_ID = "BUNDLE_CHAT_ROOM_ID" private const val BUNDLE_CHAT_ROOM_ID = "BUNDLE_CHAT_ROOM_ID"
fun newInstance(chatRoomId: String?): Fragment = ChatRoomsFragment().apply { fun newInstance(chatRoomId: String?): Fragment = ChatRoomsFragment().apply {
arguments = Bundle(1).apply { arguments = Bundle(1).apply {
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId) putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
...@@ -103,6 +103,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -103,6 +103,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
with((activity as AppCompatActivity)) { with((activity as AppCompatActivity)) {
with(toolbar) { with(toolbar) {
setSupportActionBar(this) setSupportActionBar(this)
supportActionBar?.setDisplayShowTitleEnabled(false)
setNavigationOnClickListener { presenter.toSettings() } setNavigationOnClickListener { presenter.toSettings() }
} }
} }
...@@ -122,10 +123,10 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -122,10 +123,10 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
if (isSortByName) { if (isSortByName) {
text_sort_by.text = text_sort_by.text =
getString(R.string.msg_sort_by, getString(R.string.msg_sort_by_name).toLowerCase()) getString(R.string.msg_sort_by_placeholder, getString(R.string.msg_sort_by_name).toLowerCase())
} else { } else {
text_sort_by.text = getString( text_sort_by.text = getString(
R.string.msg_sort_by, R.string.msg_sort_by_placeholder,
getString(R.string.msg_sort_by_activity).toLowerCase() getString(R.string.msg_sort_by_activity).toLowerCase()
) )
} }
...@@ -149,12 +150,14 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -149,12 +150,14 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
// We need to show all the menu items here by invalidating the options to recreate the entire menu. // We need to show all the menu items here by invalidating the options to recreate the entire menu.
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
queryChatRoomsByName(null) queryChatRoomsByName(null)
hideDirectoryView()
return true return true
} }
override fun onMenuItemActionExpand(item: MenuItem): Boolean { override fun onMenuItemActionExpand(item: MenuItem): Boolean {
// We need to hide the all the menu items here. // We need to hide the all the menu items here.
menu.findItem(R.id.action_new_channel).isVisible = false menu.findItem(R.id.action_new_channel).isVisible = false
showDirectoryView()
return true return true
} }
}) })
...@@ -282,6 +285,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -282,6 +285,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
chat.rocket.android.sortingandgrouping.ui.TAG chat.rocket.android.sortingandgrouping.ui.TAG
) )
} }
text_directory.setOnClickListener { presenter.toDirectory() }
} }
fun sortChatRoomsList( fun sortChatRoomsList(
...@@ -305,7 +310,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -305,7 +310,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
} }
private fun changeSortByTitle(text: String) { private fun changeSortByTitle(text: String) {
text_sort_by.text = getString(R.string.msg_sort_by, text.toLowerCase()) text_sort_by.text = getString(R.string.msg_sort_by_placeholder, text.toLowerCase())
} }
private fun queryChatRoomsByName(name: String?): Boolean { private fun queryChatRoomsByName(name: String?): Boolean {
...@@ -324,4 +329,14 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -324,4 +329,14 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
viewModel.setQuery(Query.ByActivity(isGroupByType)) viewModel.setQuery(Query.ByActivity(isGroupByType))
} }
} }
private fun showDirectoryView() {
text_directory.isVisible = true
text_sort_by.isGone = true
}
private fun hideDirectoryView() {
text_directory.isGone = true
text_sort_by.isVisible = true
}
} }
...@@ -9,7 +9,7 @@ import chat.rocket.android.chatrooms.adapter.LoadingItemHolder ...@@ -9,7 +9,7 @@ import chat.rocket.android.chatrooms.adapter.LoadingItemHolder
import chat.rocket.android.chatrooms.adapter.RoomUiModelMapper import chat.rocket.android.chatrooms.adapter.RoomUiModelMapper
import chat.rocket.android.chatrooms.domain.FetchChatRoomsInteractor import chat.rocket.android.chatrooms.domain.FetchChatRoomsInteractor
import chat.rocket.android.chatrooms.infrastructure.ChatRoomsRepository import chat.rocket.android.chatrooms.infrastructure.ChatRoomsRepository
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infrastructure.ConnectionManager
import chat.rocket.android.util.livedata.transform import chat.rocket.android.util.livedata.transform
import chat.rocket.android.util.livedata.wrap import chat.rocket.android.util.livedata.wrap
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
......
...@@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModelProvider ...@@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModelProvider
import chat.rocket.android.chatrooms.adapter.RoomUiModelMapper import chat.rocket.android.chatrooms.adapter.RoomUiModelMapper
import chat.rocket.android.chatrooms.domain.FetchChatRoomsInteractor import chat.rocket.android.chatrooms.domain.FetchChatRoomsInteractor
import chat.rocket.android.chatrooms.infrastructure.ChatRoomsRepository import chat.rocket.android.chatrooms.infrastructure.ChatRoomsRepository
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infrastructure.ConnectionManager
import javax.inject.Inject import javax.inject.Inject
class ChatRoomsViewModelFactory @Inject constructor( class ChatRoomsViewModelFactory @Inject constructor(
......
package chat.rocket.android.core.behaviours
interface AppLanguageView {
/**
* Updates the app language
*
* @param language The app language to be updated.
* @param country Opcional. The country code to be updated.
*/
fun updateLanguage(language: String, country: String? = null)
}
\ No newline at end of file
...@@ -4,7 +4,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy ...@@ -4,7 +4,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.main.presentation.MainNavigator import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.members.uimodel.MemberUiModelMapper import chat.rocket.android.members.uimodel.MemberUiModelMapper
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
......
...@@ -14,9 +14,15 @@ import dagger.android.support.AndroidSupportInjectionModule ...@@ -14,9 +14,15 @@ import dagger.android.support.AndroidSupportInjectionModule
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
@Component(modules = [AndroidSupportInjectionModule::class, @Component(
AppModule::class, ActivityBuilder::class, ServiceBuilder::class, ReceiverBuilder::class, modules = [
AndroidWorkerInjectionModule::class]) AndroidSupportInjectionModule::class,
AppModule::class,
ActivityBuilder::class,
ServiceBuilder::class,
ReceiverBuilder::class,
AndroidWorkerInjectionModule::class]
)
interface AppComponent { interface AppComponent {
@Component.Builder @Component.Builder
......
...@@ -19,6 +19,7 @@ import chat.rocket.android.chatroom.ui.ChatRoomActivity ...@@ -19,6 +19,7 @@ import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider import chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider
import chat.rocket.android.createchannel.di.CreateChannelProvider import chat.rocket.android.createchannel.di.CreateChannelProvider
import chat.rocket.android.dagger.scope.PerActivity import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.directory.di.DirectoryFragmentProvider
import chat.rocket.android.draw.main.di.DrawModule import chat.rocket.android.draw.main.di.DrawModule
import chat.rocket.android.draw.main.ui.DrawingActivity import chat.rocket.android.draw.main.ui.DrawingActivity
import chat.rocket.android.favoritemessages.di.FavoriteMessagesFragmentProvider import chat.rocket.android.favoritemessages.di.FavoriteMessagesFragmentProvider
...@@ -70,7 +71,8 @@ abstract class ActivityBuilder { ...@@ -70,7 +71,8 @@ abstract class ActivityBuilder {
CreateChannelProvider::class, CreateChannelProvider::class,
ProfileFragmentProvider::class, ProfileFragmentProvider::class,
SettingsFragmentProvider::class, SettingsFragmentProvider::class,
AdminPanelWebViewFragmentProvider::class AdminPanelWebViewFragmentProvider::class,
DirectoryFragmentProvider::class
] ]
) )
abstract fun bindMainActivity(): MainActivity abstract fun bindMainActivity(): MainActivity
......
...@@ -12,8 +12,8 @@ import chat.rocket.android.R ...@@ -12,8 +12,8 @@ import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.AnswersAnalytics import chat.rocket.android.analytics.AnswersAnalytics
import chat.rocket.android.analytics.GoogleAnalyticsForFirebase import chat.rocket.android.analytics.GoogleAnalyticsForFirebase
import chat.rocket.android.authentication.infraestructure.SharedPreferencesMultiServerTokenRepository import chat.rocket.android.authentication.infrastructure.SharedPreferencesMultiServerTokenRepository
import chat.rocket.android.authentication.infraestructure.SharedPreferencesTokenRepository import chat.rocket.android.authentication.infrastructure.SharedPreferencesTokenRepository
import chat.rocket.android.chatroom.service.MessageService import chat.rocket.android.chatroom.service.MessageService
import chat.rocket.android.dagger.qualifier.ForAuthentication import chat.rocket.android.dagger.qualifier.ForAuthentication
import chat.rocket.android.dagger.qualifier.ForMessages import chat.rocket.android.dagger.qualifier.ForMessages
...@@ -44,19 +44,21 @@ import chat.rocket.android.server.domain.SettingsRepository ...@@ -44,19 +44,21 @@ import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.SortingAndGroupingRepository import chat.rocket.android.server.domain.SortingAndGroupingRepository
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.UsersRepository import chat.rocket.android.server.domain.UsersRepository
import chat.rocket.android.server.infraestructure.DatabaseMessageMapper import chat.rocket.android.server.infrastructure.CurrentLanguageRepository
import chat.rocket.android.server.infraestructure.DatabaseMessagesRepository import chat.rocket.android.server.infrastructure.SharedPrefsCurrentLanguageRepository
import chat.rocket.android.server.infraestructure.JobSchedulerInteractorImpl import chat.rocket.android.server.infrastructure.DatabaseMessageMapper
import chat.rocket.android.server.infraestructure.MemoryChatRoomsRepository import chat.rocket.android.server.infrastructure.DatabaseMessagesRepository
import chat.rocket.android.server.infraestructure.MemoryUsersRepository import chat.rocket.android.server.infrastructure.JobSchedulerInteractorImpl
import chat.rocket.android.server.infraestructure.SharedPreferencesAccountsRepository import chat.rocket.android.server.infrastructure.MemoryChatRoomsRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesPermissionsRepository import chat.rocket.android.server.infrastructure.MemoryUsersRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesSettingsRepository import chat.rocket.android.server.infrastructure.SharedPreferencesAccountsRepository
import chat.rocket.android.server.infraestructure.SharedPrefsAnalyticsTrackingRepository import chat.rocket.android.server.infrastructure.SharedPreferencesPermissionsRepository
import chat.rocket.android.server.infraestructure.SharedPrefsBasicAuthRepository import chat.rocket.android.server.infrastructure.SharedPreferencesSettingsRepository
import chat.rocket.android.server.infraestructure.SharedPrefsConnectingServerRepository import chat.rocket.android.server.infrastructure.SharedPrefsAnalyticsTrackingRepository
import chat.rocket.android.server.infraestructure.SharedPrefsCurrentServerRepository import chat.rocket.android.server.infrastructure.SharedPrefsBasicAuthRepository
import chat.rocket.android.server.infraestructure.SharedPrefsSortingAndGroupingRepository import chat.rocket.android.server.infrastructure.SharedPrefsConnectingServerRepository
import chat.rocket.android.server.infrastructure.SharedPrefsCurrentServerRepository
import chat.rocket.android.server.infrastructure.SharedPrefsSortingAndGroupingRepository
import chat.rocket.android.util.AppJsonAdapterFactory import chat.rocket.android.util.AppJsonAdapterFactory
import chat.rocket.android.util.BasicAuthenticatorInterceptor import chat.rocket.android.util.BasicAuthenticatorInterceptor
import chat.rocket.android.util.HttpLoggingInterceptor import chat.rocket.android.util.HttpLoggingInterceptor
...@@ -175,7 +177,6 @@ class AppModule { ...@@ -175,7 +177,6 @@ class AppModule {
fun provideSharedPreferences(context: Application) = fun provideSharedPreferences(context: Application) =
context.getSharedPreferences("rocket.chat", Context.MODE_PRIVATE) context.getSharedPreferences("rocket.chat", Context.MODE_PRIVATE)
@Provides @Provides
@ForMessages @ForMessages
fun provideMessagesSharedPreferences(context: Application) = fun provideMessagesSharedPreferences(context: Application) =
...@@ -211,6 +212,12 @@ class AppModule { ...@@ -211,6 +212,12 @@ class AppModule {
return SharedPrefsConnectingServerRepository(prefs) return SharedPrefsConnectingServerRepository(prefs)
} }
@Provides
@Singleton
fun provideCurrentLanguageRepository(prefs: SharedPreferences): CurrentLanguageRepository {
return SharedPrefsCurrentLanguageRepository(prefs)
}
@Provides @Provides
@Singleton @Singleton
fun provideSettingsRepository(localRepository: LocalRepository): SettingsRepository { fun provideSettingsRepository(localRepository: LocalRepository): SettingsRepository {
......
...@@ -6,7 +6,7 @@ import chat.rocket.android.infrastructure.LocalRepository ...@@ -6,7 +6,7 @@ import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.SharedPreferencesLocalRepository import chat.rocket.android.infrastructure.SharedPreferencesLocalRepository
import chat.rocket.android.server.domain.CurrentServerRepository import chat.rocket.android.server.domain.CurrentServerRepository
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.SharedPrefsCurrentServerRepository import chat.rocket.android.server.infrastructure.SharedPrefsCurrentServerRepository
import chat.rocket.android.util.AppJsonAdapterFactory import chat.rocket.android.util.AppJsonAdapterFactory
import chat.rocket.android.util.TimberLogger import chat.rocket.android.util.TimberLogger
import chat.rocket.common.internal.FallbackSealedClassJsonAdapter import chat.rocket.common.internal.FallbackSealedClassJsonAdapter
......
...@@ -69,7 +69,7 @@ abstract class ChatRoomDao : BaseDao<ChatRoomEntity> { ...@@ -69,7 +69,7 @@ abstract class ChatRoomDao : BaseDao<ChatRoomEntity> {
@Query(""" @Query("""
$BASE_QUERY $BASE_QUERY
$FILTER_NOT_OPENED $FILTER_NOT_OPENED
ORDER BY name ORDER BY name COLLATE NOCASE
""") """)
abstract fun getAllAlphabetically(): LiveData<List<ChatRoom>> abstract fun getAllAlphabetically(): LiveData<List<ChatRoom>>
...@@ -79,7 +79,7 @@ abstract class ChatRoomDao : BaseDao<ChatRoomEntity> { ...@@ -79,7 +79,7 @@ abstract class ChatRoomDao : BaseDao<ChatRoomEntity> {
$FILTER_NOT_OPENED $FILTER_NOT_OPENED
ORDER BY ORDER BY
$TYPE_ORDER, $TYPE_ORDER,
name name COLLATE NOCASE
""") """)
abstract fun getAllAlphabeticallyGrouped(): LiveData<List<ChatRoom>> abstract fun getAllAlphabeticallyGrouped(): LiveData<List<ChatRoom>>
......
package chat.rocket.android.directory.adapter
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.directory.uimodel.DirectoryUiModel
import chat.rocket.android.util.extensions.inflate
private const val VIEW_TYPE_CHANNELS = 0
private const val VIEW_TYPE_USERS = 1
private const val VIEW_TYPE_GLOBAL_USERS = 2
class DirectoryAdapter(private val selector: Selector) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var isSortByChannels: Boolean = true
private var isSearchForGlobalUsers: Boolean = true
private var dataSet: List<DirectoryUiModel> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
when (viewType) {
VIEW_TYPE_CHANNELS -> DirectoryChannelViewHolder(
parent.inflate(R.layout.item_directory_channel)
)
VIEW_TYPE_USERS -> DirectoryUsersViewHolder(
parent.inflate(R.layout.item_directory_user)
)
VIEW_TYPE_GLOBAL_USERS -> DirectoryGlobalUsersViewHolder(
parent.inflate(R.layout.item_directory_user)
)
else -> throw IllegalStateException("viewType must be either VIEW_TYPE_CHANNELS, VIEW_TYPE_USERS or VIEW_TYPE_GLOBAL_USERS")
}
override fun getItemCount(): Int = dataSet.size
override fun getItemViewType(position: Int): Int {
return if (isSortByChannels) {
VIEW_TYPE_CHANNELS
} else {
if (isSearchForGlobalUsers) {
VIEW_TYPE_GLOBAL_USERS
} else {
VIEW_TYPE_USERS
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) =
when (holder) {
is DirectoryChannelViewHolder -> bindDirectoryChannelViewHolder(holder, position)
is DirectoryUsersViewHolder -> bindDirectoryUsersViewHolder(holder, position)
is DirectoryGlobalUsersViewHolder -> bindDirectoryGlobalUsersViewHolder(
holder,
position
)
else -> throw IllegalStateException("Unable to bind ViewHolder. ViewHolder must be either DirectoryChannelViewHolder, DirectoryUsersViewHolder or DirectoryGlobalUsersViewHolder")
}
private fun bindDirectoryChannelViewHolder(holder: DirectoryChannelViewHolder, position: Int) {
with(dataSet[position]) {
holder.bind(this)
holder.itemView.setOnClickListener { selector.onChannelSelected(id, name) }
}
}
private fun bindDirectoryUsersViewHolder(holder: DirectoryUsersViewHolder, position: Int) {
with(dataSet[position]) {
holder.bind(this)
holder.itemView.setOnClickListener { selector.onUserSelected(username, name) }
}
}
private fun bindDirectoryGlobalUsersViewHolder(
holder: DirectoryGlobalUsersViewHolder,
position: Int
) {
with(dataSet[position]) {
holder.bind(this)
holder.itemView.setOnClickListener { selector.onGlobalUserSelected(username, name) }
}
}
fun clearData() {
dataSet = emptyList()
notifyDataSetChanged()
}
fun setSorting(isSortByChannels: Boolean, isSearchForGlobalUsers: Boolean) {
this.isSortByChannels = isSortByChannels
this.isSearchForGlobalUsers = isSearchForGlobalUsers
}
fun prependData(dataSet: List<DirectoryUiModel>) {
this.dataSet = dataSet
notifyItemRangeInserted(0, dataSet.size)
}
fun appendData(dataSet: List<DirectoryUiModel>) {
val previousDataSetSize = this.dataSet.size
this.dataSet += dataSet
notifyItemRangeInserted(previousDataSetSize, dataSet.size)
}
}
interface Selector {
fun onChannelSelected(channelId: String, channelName: String)
fun onUserSelected(username: String, name: String)
fun onGlobalUserSelected(username: String, name: String)
}
\ No newline at end of file
package chat.rocket.android.directory.adapter
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.directory.uimodel.DirectoryUiModel
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.item_directory_channel.view.*
class DirectoryChannelViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(directoryChannelUiModel: DirectoryUiModel) = with(itemView) {
Glide.with(image_avatar).load(directoryChannelUiModel.channelAvatarUri).into(image_avatar)
text_channel_name.text = directoryChannelUiModel.name
text_channel_description.text = directoryChannelUiModel.description
text_channel_total_members.text = directoryChannelUiModel.totalMembers
}
}
\ No newline at end of file
package chat.rocket.android.directory.adapter
import android.view.View
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.directory.uimodel.DirectoryUiModel
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.item_directory_user.view.*
class DirectoryGlobalUsersViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(directoryChannelUiModel: DirectoryUiModel) = with(itemView) {
Glide.with(image_avatar).load(directoryChannelUiModel.userAvatarUri).into(image_avatar)
text_user_name.text = directoryChannelUiModel.name
text_user_username.text = directoryChannelUiModel.username
with(text_server_url) {
text = directoryChannelUiModel.serverUrl
isVisible = true
}
}
}
\ No newline at end of file
package chat.rocket.android.directory.adapter
import android.view.View
import androidx.core.view.isGone
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.directory.uimodel.DirectoryUiModel
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.item_directory_user.view.*
class DirectoryUsersViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(directoryChannelUiModel: DirectoryUiModel) = with(itemView) {
Glide.with(image_avatar).load(directoryChannelUiModel.userAvatarUri).into(image_avatar)
text_user_name.text = directoryChannelUiModel.name
text_user_username.text = directoryChannelUiModel.username
text_server_url.isGone = true
}
}
\ No newline at end of file
package chat.rocket.android.directory.di
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.directory.presentation.DirectoryView
import chat.rocket.android.directory.ui.DirectoryFragment
import dagger.Module
import dagger.Provides
@Module
class DirectoryFragmentModule {
@Provides
@PerFragment
fun directoryView(frag: DirectoryFragment): DirectoryView = frag
}
\ No newline at end of file
package chat.rocket.android.directory.di
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.directory.ui.DirectoryFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class DirectoryFragmentProvider {
@ContributesAndroidInjector(modules = [DirectoryFragmentModule::class])
@PerFragment
abstract fun provideDirectoryFragment(): DirectoryFragment
}
\ No newline at end of file
package chat.rocket.android.directory.presentation
import chat.rocket.android.chatrooms.domain.FetchChatRoomsInteractor
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.model.ChatRoomEntity
import chat.rocket.android.directory.uimodel.DirectoryUiModelMapper
import chat.rocket.android.helper.UserHelper
import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.DirectoryRequestType
import chat.rocket.core.internal.rest.DirectoryWorkspaceType
import chat.rocket.core.internal.rest.createDirectMessage
import chat.rocket.core.internal.rest.directory
import chat.rocket.core.internal.rest.getInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Named
class DirectoryPresenter @Inject constructor(
private val view: DirectoryView,
private val navigator: MainNavigator,
private val strategy: CancelStrategy,
@Named("currentServer") private val currentServer: String,
private val dbManager: DatabaseManager,
private val userHelper: UserHelper,
val factory: RocketChatClientFactory,
private val mapper: DirectoryUiModelMapper
) {
private val client: RocketChatClient = factory.get(currentServer)
private var offset: Long = 0
fun loadAllDirectoryChannels(query: String? = null) {
launchUI(strategy) {
try {
view.showLoading()
val directoryResult = client.directory(
text = query,
directoryRequestType = DirectoryRequestType.Channels(),
offset = offset,
count = 60
)
val directoryUiModels = mapper.mapToUiModelList(directoryResult.result)
view.showChannels(directoryUiModels)
offset += 1 * 60L
} catch (exception: Exception) {
exception.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
}
}
}
fun loadAllDirectoryUsers(isSearchForGlobalUsers: Boolean, query: String? = null) {
launchUI(strategy) {
try {
view.showLoading()
val directoryResult = client.directory(
text = query,
directoryRequestType = DirectoryRequestType.Users(),
directoryWorkspaceType = if (isSearchForGlobalUsers) {
DirectoryWorkspaceType.All()
} else {
DirectoryWorkspaceType.Local()
},
offset = offset,
count = 60
)
val directoryUiModels = mapper.mapToUiModelList(directoryResult.result)
view.showUsers(directoryUiModels)
offset += 1 * 60L
} catch (exception: Exception) {
exception.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
}
}
}
fun updateSorting(
isSortByChannels: Boolean,
isSearchForGlobalUsers: Boolean,
query: String? = null
) {
resetOffset()
if (isSortByChannels) {
loadAllDirectoryChannels(query)
} else {
loadAllDirectoryUsers(isSearchForGlobalUsers, query)
}
}
fun toChannel(channelId: String, name: String) {
launchUI(strategy) {
try {
view.showLoading()
withContext(Dispatchers.Default) {
val chatRoom = client.getInfo(channelId, name, roomTypeOf(RoomType.CHANNEL))
navigator.toChatRoom(
chatRoomId = channelId,
chatRoomName = name,
chatRoomType = RoomType.CHANNEL,
isReadOnly = chatRoom.readonly,
chatRoomLastSeen = -1,
isSubscribed = false,
isCreator = false,
isFavorite = false
)
}
} catch (ex: Exception) {
Timber.e(ex)
ex.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
}
}
}
fun tiDirectMessage(username: String, name: String) {
launchUI(strategy) {
try {
view.showLoading()
withContext(Dispatchers.Default) {
val directMessage = client.createDirectMessage(username)
val chatRoomEntity = ChatRoomEntity(
id = directMessage.id,
name = username,
description = null,
type = RoomType.DIRECT_MESSAGE,
fullname = name,
subscriptionId = "",
updatedAt = directMessage.updatedAt
)
dbManager.insertOrReplaceRoom(chatRoomEntity)
FetchChatRoomsInteractor(client, dbManager).refreshChatRooms()
navigator.toChatRoom(
chatRoomId = chatRoomEntity.id,
chatRoomName = chatRoomEntity.name,
chatRoomType = chatRoomEntity.type,
isReadOnly = false,
chatRoomLastSeen = -1,
isSubscribed = chatRoomEntity.open,
isCreator = true,
isFavorite = false
)
}
} catch (ex: Exception) {
Timber.e(ex)
ex.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
}
}
}
private fun resetOffset() {
offset = 0
}
}
\ No newline at end of file
package chat.rocket.android.directory.presentation
import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView
import chat.rocket.android.directory.uimodel.DirectoryUiModel
interface DirectoryView : MessageView, LoadingView {
/**
* Shows the list of directory channels.
*
* @param dataSet The data set to show.
*/
fun showChannels(dataSet: List<DirectoryUiModel>)
/**
* Shows the list of directory users.
*
* @param dataSet The data set to show.
*/
fun showUsers(dataSet: List<DirectoryUiModel>)
}
\ No newline at end of file
package chat.rocket.android.directory.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.directory.adapter.DirectoryAdapter
import chat.rocket.android.directory.adapter.Selector
import chat.rocket.android.directory.presentation.DirectoryPresenter
import chat.rocket.android.directory.presentation.DirectoryView
import chat.rocket.android.directory.uimodel.DirectoryUiModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.util.extension.onQueryTextListener
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.isNotNullNorBlank
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.fragment_directory.*
import kotlinx.android.synthetic.main.fragment_settings.view_loading
import javax.inject.Inject
internal const val TAG_DIRECTORY_FRAGMENT = "DirectoryFragment"
fun newInstance(): Fragment = DirectoryFragment()
class DirectoryFragment : Fragment(), DirectoryView {
@Inject lateinit var analyticsManager: AnalyticsManager
@Inject lateinit var presenter: DirectoryPresenter
private var isSortByChannels: Boolean = true
private var isSearchForGlobalUsers: Boolean = false
private val linearLayoutManager = LinearLayoutManager(context)
private val directoryAdapter = DirectoryAdapter(object : Selector {
override fun onChannelSelected(channelId: String, channelName: String) {
presenter.toChannel(channelId, channelName)
}
override fun onUserSelected(username: String, name: String) {
presenter.tiDirectMessage(username, name)
}
override fun onGlobalUserSelected(username: String, name: String) {
presenter.tiDirectMessage(username, name)
}
})
private val hashtagDrawable by lazy {
DrawableHelper.getDrawableFromId(R.drawable.ic_hashtag_16dp, text_sort_by.context)
}
private val userDrawable by lazy {
DrawableHelper.getDrawableFromId(R.drawable.ic_user_16dp, text_sort_by.context)
}
private val arrowDownDrawable by lazy {
DrawableHelper.getDrawableFromId(R.drawable.ic_arrow_down, text_sort_by.context)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = container?.inflate(R.layout.fragment_directory)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupRecyclerView()
setupListeners()
presenter.loadAllDirectoryChannels()
analyticsManager.logScreenView(ScreenViewEvent.Directory)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.directory, menu)
val searchMenuItem = menu.findItem(R.id.action_search)
val searchView = searchMenuItem?.actionView as SearchView
with(searchView) {
setIconifiedByDefault(false)
maxWidth = Integer.MAX_VALUE
onQueryTextListener { updateSorting(isSortByChannels, isSearchForGlobalUsers, it) }
}
searchMenuItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
updateSorting(isSortByChannels, isSearchForGlobalUsers, reload = true)
return true
}
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
return true
}
})
}
override fun showChannels(dataSet: List<DirectoryUiModel>) {
ui {
if (directoryAdapter.itemCount == 0) {
directoryAdapter.prependData(dataSet)
if (dataSet.size >= 60) {
recycler_view.addOnScrollListener(object :
EndlessRecyclerViewScrollListener(linearLayoutManager) {
override fun onLoadMore(
page: Int,
totalItemsCount: Int,
recyclerView: RecyclerView
) {
presenter.loadAllDirectoryChannels()
}
})
}
} else {
directoryAdapter.appendData(dataSet)
}
}
}
override fun showUsers(dataSet: List<DirectoryUiModel>) {
ui {
if (directoryAdapter.itemCount == 0) {
directoryAdapter.prependData(dataSet)
if (dataSet.size >= 60) {
recycler_view.addOnScrollListener(object :
EndlessRecyclerViewScrollListener(linearLayoutManager) {
override fun onLoadMore(
page: Int,
totalItemsCount: Int,
recyclerView: RecyclerView
) {
presenter.loadAllDirectoryUsers(isSearchForGlobalUsers)
}
})
}
} else {
directoryAdapter.appendData(dataSet)
}
}
}
override fun showMessage(resId: Int) {
ui { showToast(resId) }
}
override fun showMessage(message: String) {
ui { showToast(message) }
}
override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error))
override fun showLoading() {
view_loading.isVisible = true
}
override fun hideLoading() {
view_loading.isVisible = false
}
fun updateSorting(
isSortByChannels: Boolean,
isSearchForGlobalUsers: Boolean,
query: String? = null,
reload: Boolean = false
) {
if (query.isNotNullNorBlank() || reload) {
directoryAdapter.clearData()
presenter.updateSorting(isSortByChannels, isSearchForGlobalUsers, query)
}
if (this.isSortByChannels != isSortByChannels ||
this.isSearchForGlobalUsers != isSearchForGlobalUsers
) {
this.isSortByChannels = isSortByChannels
this.isSearchForGlobalUsers = isSearchForGlobalUsers
updateSortByTitle()
with(directoryAdapter) {
clearData()
setSorting(isSortByChannels, isSearchForGlobalUsers)
}
presenter.updateSorting(isSortByChannels, isSearchForGlobalUsers, query)
}
}
private fun setupToolbar() {
with((activity as AppCompatActivity)) {
with(toolbar) {
setSupportActionBar(this)
title = getString(R.string.msg_directory)
setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
setNavigationOnClickListener { activity?.onBackPressed() }
}
}
}
private fun setupRecyclerView() {
ui {
with(recycler_view) {
layoutManager = linearLayoutManager
addItemDecoration(DividerItemDecoration(it, DividerItemDecoration.HORIZONTAL))
adapter = directoryAdapter
}
}
}
private fun setupListeners() {
text_sort_by.setOnClickListener {
activity?.supportFragmentManager?.let {
showDirectorySortingBottomSheetFragment(isSortByChannels, isSearchForGlobalUsers, it)
}
}
}
private fun updateSortByTitle() {
if (isSortByChannels) {
text_sort_by.text = getString(R.string.msg_channels)
DrawableHelper.compoundLeftAndRightDrawable(
text_sort_by,
hashtagDrawable,
arrowDownDrawable
)
} else {
text_sort_by.text = getString(R.string.msg_users)
DrawableHelper.compoundLeftAndRightDrawable(
text_sort_by,
userDrawable,
arrowDownDrawable
)
}
}
}
\ No newline at end of file
package chat.rocket.android.directory.ui
import DrawableHelper
import android.content.DialogInterface
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.FragmentManager
import chat.rocket.android.R
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.bottom_seet_fragment_directory_sorting.*
fun showDirectorySortingBottomSheetFragment(
isSortByChannels: Boolean,
isSearchForGlobalUsers: Boolean,
supportFragmentManager: FragmentManager
) = DirectorySortingBottomSheetFragment().apply {
arguments = Bundle(2).apply {
putBoolean(BUNDLE_IS_SORT_BY_CHANNELS, isSortByChannels)
putBoolean(BUNDLE_IS_SEARCH_FOR_GLOBAL_USERS, isSearchForGlobalUsers)
}
}.show(supportFragmentManager, TAG)
internal const val TAG = "DirectorySortingBottomSheetFragment"
private const val BUNDLE_IS_SORT_BY_CHANNELS = "is_sort_by_channels"
private const val BUNDLE_IS_SEARCH_FOR_GLOBAL_USERS = "is_search_for_global_users"
class DirectorySortingBottomSheetFragment : BottomSheetDialogFragment() {
private var isSortByChannels = true
private var isSearchForGlobalUsers = false
private val hashtagDrawable by lazy {
DrawableHelper.getDrawableFromId(R.drawable.ic_hashtag_16dp, requireContext())
}
private val userDrawable by lazy {
DrawableHelper.getDrawableFromId(R.drawable.ic_user_16dp, requireContext())
}
private val checkDrawable by lazy {
DrawableHelper.getDrawableFromId(R.drawable.ic_check, requireContext())
}
private val directoryFragment by lazy {
activity?.supportFragmentManager?.findFragmentByTag(TAG_DIRECTORY_FRAGMENT) as DirectoryFragment
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.run {
isSortByChannels = getBoolean(BUNDLE_IS_SORT_BY_CHANNELS)
isSearchForGlobalUsers = getBoolean(BUNDLE_IS_SEARCH_FOR_GLOBAL_USERS)
}
?: requireNotNull(arguments) { "no arguments supplied when the bottom sheet fragment was instantiated" }
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
inflater.inflate(R.layout.bottom_seet_fragment_directory_sorting, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupView()
setupListeners()
}
override fun onCancel(dialog: DialogInterface?) {
super.onCancel(dialog)
directoryFragment.updateSorting(isSortByChannels, isSearchForGlobalUsers)
}
private fun setupView() {
if (isSortByChannels) {
checkSelection(text_channels, hashtagDrawable)
} else {
checkSelection(text_users, userDrawable)
}
switch_global_users.isChecked = isSearchForGlobalUsers
}
private fun setupListeners() {
text_channels.setOnClickListener {
checkSelection(text_channels, hashtagDrawable)
uncheckSelection(text_users, userDrawable)
isSortByChannels = true
}
text_users.setOnClickListener {
checkSelection(text_users, userDrawable)
uncheckSelection(text_channels, hashtagDrawable)
isSortByChannels = false
}
switch_global_users.setOnCheckedChangeListener { _, isChecked ->
isSearchForGlobalUsers = isChecked
}
}
private fun checkSelection(textView: TextView, leftDrawable: Drawable) {
context?.let {
DrawableHelper.compoundLeftAndRightDrawable(
textView,
leftDrawable,
checkDrawable
)
}
}
private fun uncheckSelection(textView: TextView, leftDrawable: Drawable) {
context?.let {
DrawableHelper.compoundLeftDrawable(
textView,
leftDrawable
)
}
}
}
\ No newline at end of file
package chat.rocket.android.directory.uimodel
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.core.model.DirectoryResult
class DirectoryUiModel(
private val directoryResult: DirectoryResult,
private val baseUrl: String?
) {
val id: String = directoryResult.id
val channelAvatarUri: String?
val userAvatarUri: String?
val name: String = directoryResult.name
val username: String = "@${directoryResult.username}"
val serverUrl: String = "" // TODO
val description: String = "" // TODO
val totalMembers: String = "" // TODO
init {
channelAvatarUri = getChannelAvatar()
userAvatarUri = getUserAvatar()
}
private fun getChannelAvatar(): String? {
return baseUrl?.avatarUrl(name, isGroupOrChannel = true)
}
private fun getUserAvatar(): String? {
return directoryResult.username?.let {
baseUrl?.avatarUrl(it)
}
}
}
package chat.rocket.android.directory.uimodel
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.baseUrl
import chat.rocket.core.model.DirectoryResult
import chat.rocket.core.model.Value
import javax.inject.Inject
import javax.inject.Named
class DirectoryUiModelMapper @Inject constructor(
getSettingsInteractor: GetSettingsInteractor,
@Named("currentServer") private val currentServer: String
) {
private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(currentServer)
private val baseUrl = settings.baseUrl()
fun mapToUiModelList(directoryList: List<DirectoryResult>): List<DirectoryUiModel> {
return directoryList.map { DirectoryUiModel(it, baseUrl) }
}
}
\ No newline at end of file
...@@ -3,7 +3,7 @@ package chat.rocket.android.favoritemessages.presentation ...@@ -3,7 +3,7 @@ package chat.rocket.android.favoritemessages.presentation
import chat.rocket.android.chatroom.uimodel.UiModelMapper import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
......
...@@ -5,7 +5,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy ...@@ -5,7 +5,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.files.uimodel.FileUiModel import chat.rocket.android.files.uimodel.FileUiModel
import chat.rocket.android.files.uimodel.FileUiModelMapper import chat.rocket.android.files.uimodel.FileUiModelMapper
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
......
...@@ -3,7 +3,7 @@ package chat.rocket.android.helper ...@@ -3,7 +3,7 @@ package chat.rocket.android.helper
object JitsiHelper { object JitsiHelper {
/** /**
* Returns the for the Jitsi video conferencing URL. * Returns the Jitsi video conferencing URL.
* *
* @param isSecureProtocol True if using SSL, false otherwise - from the public settings. * @param isSecureProtocol True if using SSL, false otherwise - from the public settings.
* @param domain The Jitsi domain - from public settings. * @param domain The Jitsi domain - from public settings.
......
...@@ -94,10 +94,16 @@ class MessageParser @Inject constructor( ...@@ -94,10 +94,16 @@ class MessageParser @Inject constructor(
} }
private fun getMention(user: SimpleUser): String { private fun getMention(user: SimpleUser): String {
user.id?.let {
if (SYSTEM_MENTIONS.contains(it)) {
return "@$it"
}
}
return if (settings.useRealName()) { return if (settings.useRealName()) {
user.name ?: "@${user.username}" user.name ?: user.username.orEmpty()
} else { } else {
"@${user.username}" user.username.orEmpty()
} }
} }
...@@ -527,5 +533,7 @@ class MessageParser @Inject constructor( ...@@ -527,5 +533,7 @@ class MessageParser @Inject constructor(
*/ */
private val WEB_URL = Pattern.compile( private val WEB_URL = Pattern.compile(
"($WEB_URL_WITH_PROTOCOL|$WEB_URL_WITHOUT_PROTOCOL)") "($WEB_URL_WITH_PROTOCOL|$WEB_URL_WITHOUT_PROTOCOL)")
private val SYSTEM_MENTIONS = arrayOf("all", "here")
} }
} }
...@@ -15,11 +15,11 @@ object OauthHelper { ...@@ -15,11 +15,11 @@ object OauthHelper {
"\"isCordova\":true}").encodeToBase64() "\"isCordova\":true}").encodeToBase64()
/** /**
* Returns the Github Oauth URL. * Returns the GitHub Oauth URL.
* *
* @param clientId The GitHub client ID. * @param clientId The GitHub client ID.
* @param state An unguessable random string used to protect against forgery attacks. * @param state An unguessable random string used to protect against forgery attacks.
* @return The Github Oauth URL. * @return The GitHub Oauth URL.
*/ */
fun getGithubOauthUrl(clientId: String, state: String): String { fun getGithubOauthUrl(clientId: String, state: String): String {
return "https://github.com/login/oauth/authorize" + return "https://github.com/login/oauth/authorize" +
...@@ -46,12 +46,12 @@ object OauthHelper { ...@@ -46,12 +46,12 @@ object OauthHelper {
} }
/** /**
* Returns the Linkedin Oauth URL. * Returns the LinkedIn Oauth URL.
* *
* @param clientId The Linkedin client ID. * @param clientId The LinkedIn client ID.
* @param serverUrl The server URL. * @param serverUrl The server URL.
* @param state An unguessable random string used to protect against forgery attacks. * @param state An unguessable random string used to protect against forgery attacks.
* @return The Linkedin Oauth URL. * @return The LinkedIn Oauth URL.
*/ */
fun getLinkedinOauthUrl(clientId: String, serverUrl: String, state: String): String { fun getLinkedinOauthUrl(clientId: String, serverUrl: String, state: String): String {
return "https://linkedin.com/oauth/v2/authorization" + return "https://linkedin.com/oauth/v2/authorization" +
...@@ -62,13 +62,13 @@ object OauthHelper { ...@@ -62,13 +62,13 @@ object OauthHelper {
} }
/** /**
* Returns the Gitlab Oauth URL. * Returns the GitLab Oauth URL.
* *
* @param host The Gitlab host. * @param host The GitLab host.
* @param clientId The Gitlab client ID. * @param clientId The GitLab client ID.
* @param serverUrl The server URL. * @param serverUrl The server URL.
* @param state An unguessable random string used to protect against forgery attacks. * @param state An unguessable random string used to protect against forgery attacks.
* @return The Gitlab Oauth URL. * @return The GitLab Oauth URL.
*/ */
fun getGitlabOauthUrl( fun getGitlabOauthUrl(
host: String? = "https://gitlab.com", host: String? = "https://gitlab.com",
......
package chat.rocket.android.main.di package chat.rocket.android.main.di
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.behaviours.AppLanguageView
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.main.presentation.MainNavigator import chat.rocket.android.main.presentation.MainNavigator
...@@ -16,6 +17,12 @@ class MainModule { ...@@ -16,6 +17,12 @@ class MainModule {
@PerActivity @PerActivity
fun provideMainNavigator(activity: MainActivity) = MainNavigator(activity) fun provideMainNavigator(activity: MainActivity) = MainNavigator(activity)
@Provides
@PerActivity
fun appLanguageView(activity: MainActivity): AppLanguageView {
return activity
}
@Provides @Provides
@PerActivity @PerActivity
fun provideJob() = Job() fun provideJob() = Job()
......
...@@ -5,6 +5,7 @@ import chat.rocket.android.authentication.ui.newServerIntent ...@@ -5,6 +5,7 @@ import chat.rocket.android.authentication.ui.newServerIntent
import chat.rocket.android.chatroom.ui.chatRoomIntent import chat.rocket.android.chatroom.ui.chatRoomIntent
import chat.rocket.android.chatrooms.ui.TAG_CHAT_ROOMS_FRAGMENT import chat.rocket.android.chatrooms.ui.TAG_CHAT_ROOMS_FRAGMENT
import chat.rocket.android.createchannel.ui.TAG_CREATE_CHANNEL_FRAGMENT import chat.rocket.android.createchannel.ui.TAG_CREATE_CHANNEL_FRAGMENT
import chat.rocket.android.directory.ui.TAG_DIRECTORY_FRAGMENT
import chat.rocket.android.main.ui.MainActivity import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.profile.ui.TAG_PROFILE_FRAGMENT import chat.rocket.android.profile.ui.TAG_PROFILE_FRAGMENT
import chat.rocket.android.server.ui.changeServerIntent import chat.rocket.android.server.ui.changeServerIntent
...@@ -28,6 +29,12 @@ class MainNavigator(internal val activity: MainActivity) { ...@@ -28,6 +29,12 @@ class MainNavigator(internal val activity: MainActivity) {
} }
} }
fun toDirectory() {
activity.addFragmentBackStack(TAG_DIRECTORY_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.directory.ui.newInstance()
}
}
fun toCreateChannel() { fun toCreateChannel() {
activity.addFragmentBackStack(TAG_CREATE_CHANNEL_FRAGMENT, R.id.fragment_container) { activity.addFragmentBackStack(TAG_CREATE_CHANNEL_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.createchannel.ui.newInstance() chat.rocket.android.createchannel.ui.newInstance()
......
package chat.rocket.android.main.presentation package chat.rocket.android.main.presentation
import chat.rocket.android.core.behaviours.AppLanguageView
import chat.rocket.android.push.GroupedPush import chat.rocket.android.push.GroupedPush
import chat.rocket.android.server.domain.GetCurrentLanguageInteractor
import chat.rocket.android.server.domain.RefreshPermissionsInteractor import chat.rocket.android.server.domain.RefreshPermissionsInteractor
import chat.rocket.android.server.domain.RefreshSettingsInteractor import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named import javax.inject.Named
class MainPresenter @Inject constructor( class MainPresenter @Inject constructor(
@Named("currentServer") private val currentServerUrl: String, @Named("currentServer") private val currentServerUrl: String,
private val mainNavigator: MainNavigator, private val mainNavigator: MainNavigator,
private val appLanguageView: AppLanguageView,
private val refreshSettingsInteractor: RefreshSettingsInteractor, private val refreshSettingsInteractor: RefreshSettingsInteractor,
private val refreshPermissionsInteractor: RefreshPermissionsInteractor, private val refreshPermissionsInteractor: RefreshPermissionsInteractor,
private val connectionManagerFactory: ConnectionManagerFactory, private val connectionManagerFactory: ConnectionManagerFactory,
private var getLanguageInteractor: GetCurrentLanguageInteractor,
private val groupedPush: GroupedPush private val groupedPush: GroupedPush
) { ) {
...@@ -31,4 +35,13 @@ class MainPresenter @Inject constructor( ...@@ -31,4 +35,13 @@ class MainPresenter @Inject constructor(
} }
fun showChatList(chatRoomId: String? = null) = mainNavigator.toChatList(chatRoomId) fun showChatList(chatRoomId: String? = null) = mainNavigator.toChatList(chatRoomId)
fun getAppLanguage() {
with(getLanguageInteractor) {
getLanguage()?.let { language ->
appLanguageView.updateLanguage(language, getCountry())
}
}
}
} }
\ No newline at end of file
...@@ -3,10 +3,14 @@ package chat.rocket.android.main.ui ...@@ -3,10 +3,14 @@ package chat.rocket.android.main.ui
import android.app.Activity import android.app.Activity
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.LocaleList
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.core.behaviours.AppLanguageView
import chat.rocket.android.main.presentation.MainPresenter import chat.rocket.android.main.presentation.MainPresenter
import chat.rocket.android.push.refreshPushToken import chat.rocket.android.push.refreshPushToken
import chat.rocket.android.server.ui.INTENT_CHAT_ROOM_ID import chat.rocket.android.server.ui.INTENT_CHAT_ROOM_ID
...@@ -15,10 +19,11 @@ import dagger.android.AndroidInjector ...@@ -15,10 +19,11 @@ import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector import dagger.android.DispatchingAndroidInjector
import dagger.android.HasActivityInjector import dagger.android.HasActivityInjector
import dagger.android.support.HasSupportFragmentInjector import dagger.android.support.HasSupportFragmentInjector
import java.util.*
import javax.inject.Inject import javax.inject.Inject
class MainActivity : AppCompatActivity(), HasActivityInjector, class MainActivity : AppCompatActivity(), HasActivityInjector,
HasSupportFragmentInjector { HasSupportFragmentInjector, AppLanguageView {
@Inject @Inject
lateinit var activityDispatchingAndroidInjector: DispatchingAndroidInjector<Activity> lateinit var activityDispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
@Inject @Inject
...@@ -30,11 +35,11 @@ class MainActivity : AppCompatActivity(), HasActivityInjector, ...@@ -30,11 +35,11 @@ class MainActivity : AppCompatActivity(), HasActivityInjector,
AndroidInjection.inject(this) AndroidInjection.inject(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
refreshPushToken() refreshPushToken()
with(presenter) { with(presenter) {
connect() connect()
getAppLanguage()
intent.getStringExtra(INTENT_CHAT_ROOM_ID).let { intent.getStringExtra(INTENT_CHAT_ROOM_ID).let {
clearNotificationsForChatRoom(it) clearNotificationsForChatRoom(it)
showChatList(it) showChatList(it)
...@@ -53,6 +58,28 @@ class MainActivity : AppCompatActivity(), HasActivityInjector, ...@@ -53,6 +58,28 @@ class MainActivity : AppCompatActivity(), HasActivityInjector,
override fun supportFragmentInjector(): AndroidInjector<Fragment> = override fun supportFragmentInjector(): AndroidInjector<Fragment> =
fagmentDispatchingAndroidInjector fagmentDispatchingAndroidInjector
override fun updateLanguage(language: String, country: String?) {
val locale: Locale = if (country != null) {
Locale(language, country)
} else {
Locale(language)
}
Locale.setDefault(locale)
val config = Configuration()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
config.locales = LocaleList(locale)
} else {
config.locale = locale
}
// TODO We need to check out a better way to use createConfigurationContext
// instead of updateConfiguration here since it is deprecated.
resources.updateConfiguration(config, resources.displayMetrics)
}
private fun clearAppNotifications() = private fun clearAppNotifications() =
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancelAll() (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancelAll()
} }
...@@ -15,10 +15,10 @@ class MembersAdapter( ...@@ -15,10 +15,10 @@ class MembersAdapter(
) : RecyclerView.Adapter<MembersAdapter.ViewHolder>() { ) : RecyclerView.Adapter<MembersAdapter.ViewHolder>() {
private var dataSet: List<MemberUiModel> = ArrayList() private var dataSet: List<MemberUiModel> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MembersAdapter.ViewHolder = override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
ViewHolder(parent.inflate(R.layout.item_member)) ViewHolder(parent.inflate(R.layout.item_member))
override fun onBindViewHolder(holder: MembersAdapter.ViewHolder, position: Int) = override fun onBindViewHolder(holder: ViewHolder, position: Int) =
holder.bind(dataSet[position], listener) holder.bind(dataSet[position], listener)
override fun getItemCount(): Int = dataSet.size override fun getItemCount(): Int = dataSet.size
......
...@@ -6,7 +6,7 @@ import chat.rocket.android.db.DatabaseManager ...@@ -6,7 +6,7 @@ import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.helper.UserHelper import chat.rocket.android.helper.UserHelper
import chat.rocket.android.members.uimodel.MemberUiModel import chat.rocket.android.members.uimodel.MemberUiModel
import chat.rocket.android.members.uimodel.MemberUiModelMapper import chat.rocket.android.members.uimodel.MemberUiModelMapper
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
......
...@@ -102,15 +102,11 @@ class MembersFragment : Fragment(), MembersView { ...@@ -102,15 +102,11 @@ class MembersFragment : Fragment(), MembersView {
} }
override fun showMessage(resId: Int) { override fun showMessage(resId: Int) {
ui { ui { showToast(resId) }
showToast(resId)
}
} }
override fun showMessage(message: String) { override fun showMessage(message: String) {
ui { ui { showToast(message) }
showToast(message)
}
} }
override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error)) override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error))
......
...@@ -2,7 +2,7 @@ package chat.rocket.android.mentions.presentention ...@@ -2,7 +2,7 @@ package chat.rocket.android.mentions.presentention
import chat.rocket.android.chatroom.uimodel.UiModelMapper import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
......
...@@ -3,7 +3,7 @@ package chat.rocket.android.pinnedmessages.presentation ...@@ -3,7 +3,7 @@ package chat.rocket.android.pinnedmessages.presentation
import chat.rocket.android.chatroom.uimodel.UiModelMapper import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
......
...@@ -11,8 +11,8 @@ import chat.rocket.android.main.presentation.MainNavigator ...@@ -11,8 +11,8 @@ import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.RemoveAccountInteractor import chat.rocket.android.server.domain.RemoveAccountInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.server.presentation.CheckServerPresenter import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extension.compressImageAndGetByteArray import chat.rocket.android.util.extension.compressImageAndGetByteArray
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
......
...@@ -141,7 +141,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -141,7 +141,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
} }
override fun showProfileUpdateSuccessfullyMessage() { override fun showProfileUpdateSuccessfullyMessage() {
showMessage(getString(R.string.msg_profile_update_successfully)) showMessage(getString(R.string.msg_profile_updated_successfully))
} }
override fun invalidateToken(token: String) = invalidateFirebaseToken(token) override fun invalidateToken(token: String) = invalidateFirebaseToken(token)
...@@ -267,8 +267,8 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -267,8 +267,8 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
text_email.asObservable() text_email.asObservable()
) { text_name, text_username, text_email -> ) { text_name, text_username, text_email ->
return@combineLatest (text_name.toString() != currentName || return@combineLatest (text_name.toString() != currentName ||
text_username.toString() != currentUsername || text_username.toString() != currentUsername ||
text_email.toString() != currentEmail) text_email.toString() != currentEmail)
}.subscribe { isValid -> }.subscribe { isValid ->
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
if (isValid) { if (isValid) {
......
...@@ -7,7 +7,7 @@ import android.content.Intent ...@@ -7,7 +7,7 @@ import android.content.Intent
import androidx.core.app.RemoteInput import androidx.core.app.RemoteInput
import android.widget.Toast import android.widget.Toast
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.core.internal.rest.sendMessage import chat.rocket.core.internal.rest.sendMessage
import dagger.android.AndroidInjection import dagger.android.AndroidInjection
......
package chat.rocket.android.server.domain
import chat.rocket.android.server.infrastructure.CurrentLanguageRepository
import javax.inject.Inject
class GetCurrentLanguageInteractor @Inject constructor(
private val repository: CurrentLanguageRepository
) {
fun getLanguage(): String? = repository.getLanguage()
fun getCountry(): String? = repository.getCountry()
}
\ No newline at end of file
package chat.rocket.android.server.domain package chat.rocket.android.server.domain
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.core.internal.rest.permissions import chat.rocket.core.internal.rest.permissions
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
......
package chat.rocket.android.server.domain package chat.rocket.android.server.domain
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.core.internal.rest.settings import chat.rocket.core.internal.rest.settings
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
......
package chat.rocket.android.server.domain
import chat.rocket.android.server.infrastructure.CurrentLanguageRepository
import javax.inject.Inject
class SaveCurrentLanguageInteractor @Inject constructor(
private val repository: CurrentLanguageRepository
) {
fun save(language: String, country: String?) = repository.save(language, country)
}
\ No newline at end of file
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import chat.rocket.android.db.DatabaseManagerFactory import chat.rocket.android.db.DatabaseManagerFactory
import timber.log.Timber import timber.log.Timber
......
package chat.rocket.android.server.infrastructure
interface CurrentLanguageRepository {
fun save(language: String, country: String? = null)
fun getLanguage(): String?
fun getCountry(): String?
}
\ No newline at end of file
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.model.* import chat.rocket.android.db.model.*
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.Operation import chat.rocket.android.db.Operation
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.app.job.JobInfo import android.app.job.JobInfo
import android.app.job.JobScheduler import android.app.job.JobScheduler
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import chat.rocket.android.server.domain.ChatRoomsRepository import chat.rocket.android.server.domain.ChatRoomsRepository
import chat.rocket.core.model.ChatRoom import chat.rocket.core.model.ChatRoom
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import chat.rocket.android.server.domain.UsersRepository import chat.rocket.android.server.domain.UsersRepository
import chat.rocket.android.server.domain.UsersRepository.Query import chat.rocket.android.server.domain.UsersRepository.Query
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.os.Build import android.os.Build
import chat.rocket.android.BuildConfig import chat.rocket.android.BuildConfig
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.core.content.edit import androidx.core.content.edit
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.PermissionsRepository import chat.rocket.android.server.domain.PermissionsRepository
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.LocalRepository.Companion.SETTINGS_KEY import chat.rocket.android.infrastructure.LocalRepository.Companion.SETTINGS_KEY
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import chat.rocket.android.server.domain.AnalyticsTrackingRepository import chat.rocket.android.server.domain.AnalyticsTrackingRepository
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.core.content.edit import androidx.core.content.edit
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import chat.rocket.android.server.domain.CurrentServerRepository import chat.rocket.android.server.domain.CurrentServerRepository
......
package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences
private const val CURRENT_LANGUAGE = "current_language"
private const val CURRENT_LANGUAGE_COUNTRY = "current_language_country"
class SharedPrefsCurrentLanguageRepository(private val preferences: SharedPreferences) :
CurrentLanguageRepository {
override fun save(language: String, country: String?) {
with(preferences) {
edit().putString(CURRENT_LANGUAGE, language).apply()
edit().putString(CURRENT_LANGUAGE_COUNTRY, country).apply()
}
}
override fun getLanguage(): String? {
return preferences.getString(CURRENT_LANGUAGE, "")
}
override fun getCountry(): String? {
return preferences.getString(CURRENT_LANGUAGE_COUNTRY, "")
}
}
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import chat.rocket.android.server.domain.CurrentServerRepository import chat.rocket.android.server.domain.CurrentServerRepository
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import chat.rocket.android.server.domain.SortingAndGroupingRepository import chat.rocket.android.server.domain.SortingAndGroupingRepository
......
...@@ -9,7 +9,7 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor ...@@ -9,7 +9,7 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.SaveCurrentServerInteractor import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import javax.inject.Inject import javax.inject.Inject
......
...@@ -26,9 +26,9 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor ...@@ -26,9 +26,9 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.RemoveAccountInteractor import chat.rocket.android.server.domain.RemoveAccountInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.RefreshSettingsInteractor import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infrastructure.ConnectionManager
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.VersionInfo import chat.rocket.android.util.VersionInfo
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.casUrl import chat.rocket.android.util.extensions.casUrl
...@@ -452,7 +452,7 @@ abstract class CheckServerPresenter constructor( ...@@ -452,7 +452,7 @@ abstract class CheckServerPresenter constructor(
/** /**
* Returns the OAuth client ID of a [serviceMap]. * Returns the OAuth client ID of a [serviceMap].
* REMARK: This function works for common OAuth providers (Google, Facebook, Github and so on) * REMARK: This function works for common OAuth providers (Google, Facebook, GitHub and so on)
* as well as custom OAuth. * as well as custom OAuth.
* *
* @param serviceMap The service map to get the OAuth client ID. * @param serviceMap The service map to get the OAuth client ID.
......
...@@ -40,7 +40,6 @@ class ServersAdapter( ...@@ -40,7 +40,6 @@ class ServersAdapter(
} }
} }
private fun bindServerViewHolder(holder: ServerViewHolder, position: Int) { private fun bindServerViewHolder(holder: ServerViewHolder, position: Int) {
val account = servers[position] val account = servers[position]
holder.bind(account) holder.bind(account)
......
...@@ -4,7 +4,7 @@ import chat.rocket.android.analytics.AnalyticsManager ...@@ -4,7 +4,7 @@ import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.UserHelper import chat.rocket.android.helper.UserHelper
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
......
...@@ -5,12 +5,14 @@ import chat.rocket.android.db.DatabaseManagerFactory ...@@ -5,12 +5,14 @@ import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.helper.UserHelper import chat.rocket.android.helper.UserHelper
import chat.rocket.android.main.presentation.MainNavigator import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.server.domain.GetCurrentLanguageInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.PermissionsInteractor import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.RemoveAccountInteractor import chat.rocket.android.server.domain.RemoveAccountInteractor
import chat.rocket.android.server.domain.SaveCurrentLanguageInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.server.presentation.CheckServerPresenter import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extension.gethash import chat.rocket.android.util.extension.gethash
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
...@@ -41,7 +43,8 @@ class SettingsPresenter @Inject constructor( ...@@ -41,7 +43,8 @@ class SettingsPresenter @Inject constructor(
getCurrentServerInteractor: GetCurrentServerInteractor, getCurrentServerInteractor: GetCurrentServerInteractor,
removeAccountInteractor: RemoveAccountInteractor, removeAccountInteractor: RemoveAccountInteractor,
databaseManagerFactory: DatabaseManagerFactory, databaseManagerFactory: DatabaseManagerFactory,
connectionManagerFactory: ConnectionManagerFactory connectionManagerFactory: ConnectionManagerFactory,
private val saveLanguageInteractor: SaveCurrentLanguageInteractor
) : CheckServerPresenter( ) : CheckServerPresenter(
strategy = strategy, strategy = strategy,
factory = rocketChatClientFactory, factory = rocketChatClientFactory,
...@@ -123,6 +126,10 @@ class SettingsPresenter @Inject constructor( ...@@ -123,6 +126,10 @@ class SettingsPresenter @Inject constructor(
} }
} }
fun saveLocale(language: String, country: String? = null) {
saveLanguageInteractor.save(language, country)
}
fun toProfile() = navigator.toProfile() fun toProfile() = navigator.toProfile()
fun toAdmin() = tokenRepository.get(currentServer)?.let { fun toAdmin() = tokenRepository.get(currentServer)?.let {
......
...@@ -17,6 +17,7 @@ import chat.rocket.android.BuildConfig ...@@ -17,6 +17,7 @@ import chat.rocket.android.BuildConfig
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.core.behaviours.AppLanguageView
import chat.rocket.android.helper.TextHelper.getDeviceAndAppInformation import chat.rocket.android.helper.TextHelper.getDeviceAndAppInformation
import chat.rocket.android.settings.presentation.SettingsPresenter import chat.rocket.android.settings.presentation.SettingsPresenter
import chat.rocket.android.settings.presentation.SettingsView import chat.rocket.android.settings.presentation.SettingsView
...@@ -33,7 +34,7 @@ internal const val TAG_SETTINGS_FRAGMENT = "SettingsFragment" ...@@ -33,7 +34,7 @@ internal const val TAG_SETTINGS_FRAGMENT = "SettingsFragment"
fun newInstance(): Fragment = SettingsFragment() fun newInstance(): Fragment = SettingsFragment()
class SettingsFragment : Fragment(), SettingsView { class SettingsFragment : Fragment(), SettingsView, AppLanguageView {
@Inject lateinit var analyticsManager: AnalyticsManager @Inject lateinit var analyticsManager: AnalyticsManager
@Inject lateinit var presenter: SettingsPresenter @Inject lateinit var presenter: SettingsPresenter
...@@ -74,14 +75,14 @@ class SettingsFragment : Fragment(), SettingsView { ...@@ -74,14 +75,14 @@ class SettingsFragment : Fragment(), SettingsView {
text_contact_us.setOnClickListener { contactSupport() } text_contact_us.setOnClickListener { contactSupport() }
text_language.setOnClickListener {} text_language.setOnClickListener { changeLanguage() }
text_review_this_app.setOnClickListener { showAppOnStore() } text_review_this_app.setOnClickListener { showAppOnStore() }
text_share_this_app.setOnClickListener { shareApp() } text_share_this_app.setOnClickListener { shareApp() }
text_license.setOnClickListener { text_license.setOnClickListener {
presenter.toLicense(getString(R.string.license_url), getString(R.string.title_licence)) presenter.toLicense(getString(R.string.license_url), getString(R.string.title_license))
} }
text_app_version.text = getString(R.string.msg_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE) text_app_version.text = getString(R.string.msg_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
...@@ -109,6 +110,11 @@ class SettingsFragment : Fragment(), SettingsView { ...@@ -109,6 +110,11 @@ class SettingsFragment : Fragment(), SettingsView {
} }
} }
override fun updateLanguage(language: String, country: String?) {
presenter.saveLocale(language, country)
activity?.recreate()
}
override fun invalidateToken(token: String) = invalidateFirebaseToken(token) override fun invalidateToken(token: String) = invalidateFirebaseToken(token)
override fun showLoading() { override fun showLoading() {
...@@ -155,6 +161,38 @@ class SettingsFragment : Fragment(), SettingsView { ...@@ -155,6 +161,38 @@ class SettingsFragment : Fragment(), SettingsView {
} }
} }
private fun changeLanguage() {
context?.let {
AlertDialog.Builder(it)
.setTitle(R.string.title_choose_language)
.setSingleChoiceItems(
resources.getStringArray(R.array.languages), -1
) { dialog, option ->
when (option) {
0 -> updateLanguage("en")
1 -> updateLanguage("ar")
2 -> updateLanguage("de")
3 -> updateLanguage("es")
4 -> updateLanguage("fa")
5 -> updateLanguage("fr")
6 -> updateLanguage("hi", "IN")
7 -> updateLanguage("it")
8 -> updateLanguage("ja")
9 -> updateLanguage("pt", "BR")
10 -> updateLanguage("pt", "PT")
11 -> updateLanguage("ru", "RU")
12 -> updateLanguage("tr")
13 -> updateLanguage("uk")
14 -> updateLanguage("zh", "CN")
15 -> updateLanguage("zh", "TW")
}
dialog.dismiss()
}
.create()
.show()
}
}
private fun showAppOnStore() { private fun showAppOnStore() {
try { try {
startActivity(Intent(Intent.ACTION_VIEW, getString(R.string.market_link).toUri())) startActivity(Intent(Intent.ACTION_VIEW, getString(R.string.market_link).toUri()))
......
...@@ -140,7 +140,7 @@ class SortingAndGroupingBottomSheetFragment : BottomSheetDialogFragment(), Sorti ...@@ -140,7 +140,7 @@ class SortingAndGroupingBottomSheetFragment : BottomSheetDialogFragment(), Sorti
} }
private fun changeSortByTitle(text: String) { private fun changeSortByTitle(text: String) {
text_sort_by.text = getString(R.string.msg_sort_by, text.toLowerCase()) text_sort_by.text = getString(R.string.msg_sort_by_placeholder, text.toLowerCase())
} }
private fun checkSelection(textView: TextView, @DrawableRes leftDrawable: Int) { private fun checkSelection(textView: TextView, @DrawableRes leftDrawable: Int) {
......
...@@ -9,7 +9,7 @@ import chat.rocket.android.db.model.UserEntity ...@@ -9,7 +9,7 @@ import chat.rocket.android.db.model.UserEntity
import chat.rocket.android.server.domain.CurrentServerRepository import chat.rocket.android.server.domain.CurrentServerRepository
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.isJitsiEnabled import chat.rocket.android.server.domain.isJitsiEnabled
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
......
...@@ -2,7 +2,7 @@ package chat.rocket.android.util.extensions ...@@ -2,7 +2,7 @@ package chat.rocket.android.util.extensions
import chat.rocket.android.db.model.MessageEntity import chat.rocket.android.db.model.MessageEntity
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.core.internal.rest.registerPushToken import chat.rocket.core.internal.rest.registerPushToken
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
......
...@@ -75,6 +75,8 @@ fun String.lowercaseUrl(): String? = HttpUrl.parse(this)?.run { ...@@ -75,6 +75,8 @@ fun String.lowercaseUrl(): String? = HttpUrl.parse(this)?.run {
fun String?.isNotNullNorEmpty(): Boolean = this != null && this.isNotEmpty() fun String?.isNotNullNorEmpty(): Boolean = this != null && this.isNotEmpty()
fun String?.isNotNullNorBlank(): Boolean = this != null && this.isNotBlank()
inline fun String?.ifNotNullNotEmpty(block: (String) -> Unit) { inline fun String?.ifNotNullNotEmpty(block: (String) -> Unit) {
if (this != null && this.isNotEmpty()) { if (this != null && this.isNotEmpty()) {
block(this) block(this)
......
...@@ -6,7 +6,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy ...@@ -6,7 +6,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.JitsiHelper import chat.rocket.android.helper.JitsiHelper
import chat.rocket.android.helper.UserHelper import chat.rocket.android.helper.UserHelper
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="7dp"
android:viewportWidth="12"
android:viewportHeight="7">
<path
android:fillColor="#EFEFEF"
android:fillType="nonZero"
android:pathData="M6,4.9512L10.4571,0.5122C10.7415,0.229 11.2013,0.229 11.4857,0.5122L11.4857,0.5122C11.7686,0.7939 11.7695,1.2516 11.4878,1.5345C11.4871,1.5352 11.4864,1.5359 11.4857,1.5366L6.7057,6.2972C6.3155,6.6858 5.6845,6.6858 5.2943,6.2972L0.5143,1.5366C0.2314,1.2549 0.2305,0.7972 0.5122,0.5143C0.5129,0.5136 0.5136,0.5129 0.5143,0.5122L0.5143,0.5122C0.7987,0.229 1.2585,0.229 1.5429,0.5122L3.5143,2.4756L6,4.9512Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#E8F2FF"
android:fillType="evenOdd"
android:pathData="M4,0L44,0A4,4 0,0 1,48 4L48,44A4,4 0,0 1,44 48L4,48A4,4 0,0 1,0 44L0,4A4,4 0,0 1,4 0z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
<path
android:fillColor="#1D74F5"
android:fillType="nonZero"
android:pathData="M20.4021,27.5L18.3698,27.5C19.0883,28.6535 20.1515,29.57 21.4153,30.1057C20.9935,29.3908 20.6468,28.5043 20.4021,27.5ZM20.126,26C20.0438,25.3608 20,24.6906 20,24C20,23.4873 20.0241,22.9859 20.0702,22.5L17.5419,22.5C17.4304,22.982 17.3714,23.4841 17.3714,24C17.3714,24.697 17.479,25.3689 17.6785,26L20.126,26ZM20.2908,21C20.5358,19.7892 20.9248,18.7257 21.4153,17.8943C19.9739,18.5052 18.7934,19.6117 18.0876,21L20.2908,21ZM27.7092,21L29.9124,21C29.2066,19.6117 28.0261,18.5052 26.5847,17.8943C27.0752,18.7257 27.4642,19.7892 27.7092,21ZM27.9298,22.5C27.9759,22.9859 28,23.4873 28,24C28,24.6906 27.9562,25.3608 27.874,26L30.3215,26C30.521,25.3689 30.6286,24.697 30.6286,24C30.6286,23.4841 30.5696,22.982 30.4581,22.5L27.9298,22.5ZM27.5979,27.5C27.3532,28.5043 27.0065,29.3908 26.5847,30.1057C27.8485,29.57 28.9117,28.6535 29.6302,27.5L27.5979,27.5ZM21.8745,27.5C22.3155,29.3609 23.1025,30.6 24,30.6C24.8975,30.6 25.6845,29.3609 26.1255,27.5L21.8745,27.5ZM21.6127,26L26.3873,26C26.4606,25.3841 26.5,24.7291 26.5,24.05C26.5,23.516 26.4756,22.9969 26.4296,22.5L21.5704,22.5C21.5244,22.9969 21.5,23.516 21.5,24.05C21.5,24.7291 21.5394,25.3841 21.6127,26ZM21.787,21L26.213,21C25.7943,18.9188 24.9604,17.5 24,17.5C23.0396,17.5 22.2057,18.9188 21.787,21ZM24,32C19.5822,32 16,28.4178 16,24C16,19.5813 19.5822,16 24,16C28.4187,16 32,19.5813 32,24C32,28.4178 28.4187,32 24,32Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment