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

Merge branch 'develop' into fix-2109

parents 923adeec 7ad32331
...@@ -43,8 +43,8 @@ cd Rocket.Chat.Android/app ...@@ -43,8 +43,8 @@ cd Rocket.Chat.Android/app
## Bug report & Feature request ## Bug report & Feature request
Are you having a technical issue trying to compile the app, or setting up Push Notifications? Please use our Community Support channel for that: https://forums.rocket.chat/c/community-support. The issues are only suppose to be used for bugs, improvements and features in the native Android application. Are you having a technical issue trying to compile the app, or setting up Push Notifications? Please use our Community Support channel for that: https://forums.rocket.chat/c/community-support. The issues are only supposed to be used for bugs, improvements, and features in the native Android application.
## Coding Style ## Coding Style
Please follow the official [Kotlin coding convections](https://kotlinlang.org/docs/reference/coding-conventions.html) when contributing. Please follow the official [Kotlin coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html) when contributing.
...@@ -34,12 +34,16 @@ class AboutFragment : Fragment() { ...@@ -34,12 +34,16 @@ class AboutFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupViews() setupViews()
analyticsManager.logScreenView(ScreenViewEvent.About) analyticsManager.logScreenView(ScreenViewEvent.About)
} }
override fun onResume() {
super.onResume()
setupToolbar()
}
private fun setupViews() { private fun setupViews() {
text_version_name.text = BuildConfig.VERSION_NAME text_version_name.text = BuildConfig.VERSION_NAME
text_build_number.text = getString( text_build_number.text = getString(
......
...@@ -3,15 +3,10 @@ package chat.rocket.android.app ...@@ -3,15 +3,10 @@ package chat.rocket.android.app
import androidx.lifecycle.Lifecycle 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.GetAccountInteractor
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.infraestructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.common.RocketChatException
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import chat.rocket.core.internal.realtime.setTemporaryStatus
import kotlinx.coroutines.experimental.launch import kotlinx.coroutines.experimental.launch
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class AppLifecycleObserver @Inject constructor( class AppLifecycleObserver @Inject constructor(
......
import android.content.Context import android.content.Context
import chat.rocket.android.R import chat.rocket.android.R
import org.threeten.bp.* import org.threeten.bp.Instant
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import org.threeten.bp.LocalTime
import org.threeten.bp.Period
import org.threeten.bp.ZoneId
import org.threeten.bp.format.DateTimeFormatter import org.threeten.bp.format.DateTimeFormatter
import org.threeten.bp.format.FormatStyle import org.threeten.bp.format.FormatStyle
import org.threeten.bp.format.TextStyle import org.threeten.bp.format.TextStyle
...@@ -53,39 +58,39 @@ object DateTimeHelper { ...@@ -53,39 +58,39 @@ object DateTimeHelper {
} }
} }
/** /**
* Returns a time from a [LocalDateTime]. * Returns a time from a [LocalDateTime].
* *
* @param localDateTime The [LocalDateTime]. * @param localDateTime The [LocalDateTime].
* @return The time from a [LocalDateTime]. * @return The time from a [LocalDateTime].
*/ */
fun getTime(localDateTime: LocalDateTime): String { fun getTime(localDateTime: LocalDateTime): String {
val formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT) val formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
return localDateTime.toLocalTime().format(formatter).toString() return localDateTime.toLocalTime().format(formatter).toString()
} }
/** /**
* Returns a date time from a [LocalDateTime]. * Returns a date time from a [LocalDateTime].
* *
* @param localDateTime The [LocalDateTime]. * @param localDateTime The [LocalDateTime].
* @return The time from a [LocalDateTime]. * @return The time from a [LocalDateTime].
*/ */
fun getDateTime(localDateTime: LocalDateTime): String { fun getDateTime(localDateTime: LocalDateTime): String {
return formatLocalDateTime(localDateTime) return formatLocalDateTime(localDateTime)
} }
private fun formatLocalDateTime(localDateTime: LocalDateTime): String { private fun formatLocalDateTime(localDateTime: LocalDateTime): String {
val formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT) val formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
return localDateTime.format(formatter).toString() return localDateTime.format(formatter).toString()
} }
private fun formatLocalDate(localDate: LocalDate): String { private fun formatLocalDate(localDate: LocalDate): String {
val formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM) val formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
return localDate.format(formatter).toString() return localDate.format(formatter).toString()
} }
private fun formatLocalTime(localTime: LocalTime): String { private fun formatLocalTime(localTime: LocalTime): String {
val formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT) val formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
return localTime.format(formatter).toString() return localTime.format(formatter).toString()
} }
} }
\ No newline at end of file
...@@ -8,19 +8,16 @@ import chat.rocket.android.server.domain.MultiServerTokenRepository ...@@ -8,19 +8,16 @@ import chat.rocket.android.server.domain.MultiServerTokenRepository
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
@PerActivity @PerActivity
class SharedPreferencesMultiServerTokenRepository(private val repository: LocalRepository, class SharedPreferencesMultiServerTokenRepository(
private val moshi: Moshi private val repository: LocalRepository,
private val moshi: Moshi
) : MultiServerTokenRepository { ) : MultiServerTokenRepository {
override fun get(server: String): TokenModel? { override fun get(server: String): TokenModel? {
val token = repository.get("$TOKEN_KEY$server") val token = repository.get("$TOKEN_KEY$server")
val adapter = moshi.adapter<TokenModel>(TokenModel::class.java) val adapter = moshi.adapter<TokenModel>(TokenModel::class.java)
token?.let { return token?.let { adapter.fromJson(it) }
return adapter.fromJson(token)
}
return null
} }
override fun save(server: String, token: TokenModel) { override fun save(server: String, token: TokenModel) {
......
...@@ -39,11 +39,9 @@ internal const val REQUEST_CODE_FOR_SIGN_IN_REQUIRED = 1 ...@@ -39,11 +39,9 @@ internal const val REQUEST_CODE_FOR_SIGN_IN_REQUIRED = 1
internal const val REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION = 2 internal const val REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION = 2
internal const val REQUEST_CODE_FOR_SAVE_RESOLUTION = 3 internal const val REQUEST_CODE_FOR_SAVE_RESOLUTION = 3
fun newInstance(serverName: String): Fragment { fun newInstance(serverName: String): Fragment = LoginFragment().apply {
return LoginFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(SERVER_NAME, serverName)
putString(SERVER_NAME, serverName)
}
} }
} }
...@@ -59,9 +57,8 @@ class LoginFragment : Fragment(), LoginView { ...@@ -59,9 +57,8 @@ class LoginFragment : Fragment(), LoginView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { serverName = getString(SERVER_NAME)
serverName = bundle.getString(SERVER_NAME)
} }
} }
...@@ -150,7 +147,7 @@ class LoginFragment : Fragment(), LoginView { ...@@ -150,7 +147,7 @@ class LoginFragment : Fragment(), LoginView {
override fun showGenericErrorMessage() = showMessage(R.string.msg_generic_error) override fun showGenericErrorMessage() = showMessage(R.string.msg_generic_error)
private fun setupOnClickListener() = private fun setupOnClickListener() =
ui { _ -> ui {
button_log_in.setOnClickListener { button_log_in.setOnClickListener {
presenter.authenticateWithUserAndPassword( presenter.authenticateWithUserAndPassword(
text_username_or_email.textContent, text_username_or_email.textContent,
...@@ -160,7 +157,7 @@ class LoginFragment : Fragment(), LoginView { ...@@ -160,7 +157,7 @@ class LoginFragment : Fragment(), LoginView {
} }
override fun showForgotPasswordView() { override fun showForgotPasswordView() {
ui { _ -> ui {
button_forgot_your_password.isVisible = true button_forgot_your_password.isVisible = true
button_forgot_your_password.setOnClickListener { presenter.forgotPassword() } button_forgot_your_password.setOnClickListener { presenter.forgotPassword() }
......
...@@ -88,36 +88,34 @@ fun newInstance( ...@@ -88,36 +88,34 @@ fun newInstance(
isLoginFormEnabled: Boolean, isLoginFormEnabled: Boolean,
isNewAccountCreationEnabled: Boolean, isNewAccountCreationEnabled: Boolean,
deepLinkInfo: LoginDeepLinkInfo? = null deepLinkInfo: LoginDeepLinkInfo? = null
): Fragment { ): Fragment = LoginOptionsFragment().apply {
return LoginOptionsFragment().apply { arguments = Bundle(23).apply {
arguments = Bundle(23).apply { putString(SERVER_NAME, serverName)
putString(SERVER_NAME, serverName) putString(STATE, state)
putString(STATE, state) putString(FACEBOOK_OAUTH_URL, facebookOauthUrl)
putString(FACEBOOK_OAUTH_URL, facebookOauthUrl) putString(GITHUB_OAUTH_URL, githubOauthUrl)
putString(GITHUB_OAUTH_URL, githubOauthUrl) putString(GOOGLE_OAUTH_URL, googleOauthUrl)
putString(GOOGLE_OAUTH_URL, googleOauthUrl) putString(LINKEDIN_OAUTH_URL, linkedinOauthUrl)
putString(LINKEDIN_OAUTH_URL, linkedinOauthUrl) putString(GITLAB_OAUTH_URL, gitlabOauthUrl)
putString(GITLAB_OAUTH_URL, gitlabOauthUrl) putString(WORDPRESS_OAUTH_URL, wordpressOauthUrl)
putString(WORDPRESS_OAUTH_URL, wordpressOauthUrl) putString(CAS_LOGIN_URL, casLoginUrl)
putString(CAS_LOGIN_URL, casLoginUrl) putString(CAS_TOKEN, casToken)
putString(CAS_TOKEN, casToken) putString(CAS_SERVICE_NAME, casServiceName)
putString(CAS_SERVICE_NAME, casServiceName) putInt(CAS_SERVICE_NAME_TEXT_COLOR, casServiceNameTextColor)
putInt(CAS_SERVICE_NAME_TEXT_COLOR, casServiceNameTextColor) putInt(CAS_SERVICE_BUTTON_COLOR, casServiceButtonColor)
putInt(CAS_SERVICE_BUTTON_COLOR, casServiceButtonColor) putString(CUSTOM_OAUTH_URL, customOauthUrl)
putString(CUSTOM_OAUTH_URL, customOauthUrl) putString(CUSTOM_OAUTH_SERVICE_NAME, customOauthServiceName)
putString(CUSTOM_OAUTH_SERVICE_NAME, customOauthServiceName) putInt(CUSTOM_OAUTH_SERVICE_NAME_TEXT_COLOR, customOauthServiceNameTextColor)
putInt(CUSTOM_OAUTH_SERVICE_NAME_TEXT_COLOR, customOauthServiceNameTextColor) putInt(CUSTOM_OAUTH_SERVICE_BUTTON_COLOR, customOauthServiceButtonColor)
putInt(CUSTOM_OAUTH_SERVICE_BUTTON_COLOR, customOauthServiceButtonColor) putString(SAML_URL, samlUrl)
putString(SAML_URL, samlUrl) putString(SAML_TOKEN, samlToken)
putString(SAML_TOKEN, samlToken) putString(SAML_SERVICE_NAME, samlServiceName)
putString(SAML_SERVICE_NAME, samlServiceName) putInt(SAML_SERVICE_NAME_TEXT_COLOR, samlServiceNameTextColor)
putInt(SAML_SERVICE_NAME_TEXT_COLOR, samlServiceNameTextColor) putInt(SAML_SERVICE_BUTTON_COLOR, samlServiceButtonColor)
putInt(SAML_SERVICE_BUTTON_COLOR, samlServiceButtonColor) putInt(TOTAL_SOCIAL_ACCOUNTS, totalSocialAccountsEnabled)
putInt(TOTAL_SOCIAL_ACCOUNTS, totalSocialAccountsEnabled) putBoolean(IS_LOGIN_FORM_ENABLED, isLoginFormEnabled)
putBoolean(IS_LOGIN_FORM_ENABLED, isLoginFormEnabled) putBoolean(IS_NEW_ACCOUNT_CREATION_ENABLED, isNewAccountCreationEnabled)
putBoolean(IS_NEW_ACCOUNT_CREATION_ENABLED, isNewAccountCreationEnabled) putParcelable(DEEP_LINK_INFO, deepLinkInfo)
putParcelable(DEEP_LINK_INFO, deepLinkInfo)
}
} }
} }
...@@ -157,34 +155,33 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView { ...@@ -157,34 +155,33 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { serverName = getString(SERVER_NAME)
serverName = bundle.getString(SERVER_NAME) state = getString(STATE)
state = bundle.getString(STATE) facebookOauthUrl = getString(FACEBOOK_OAUTH_URL)
facebookOauthUrl = bundle.getString(FACEBOOK_OAUTH_URL) githubOauthUrl = getString(GITHUB_OAUTH_URL)
githubOauthUrl = bundle.getString(GITHUB_OAUTH_URL) googleOauthUrl = getString(GOOGLE_OAUTH_URL)
googleOauthUrl = bundle.getString(GOOGLE_OAUTH_URL) linkedinOauthUrl = getString(LINKEDIN_OAUTH_URL)
linkedinOauthUrl = bundle.getString(LINKEDIN_OAUTH_URL) gitlabOauthUrl = getString(GITLAB_OAUTH_URL)
gitlabOauthUrl = bundle.getString(GITLAB_OAUTH_URL) wordpressOauthUrl = getString(WORDPRESS_OAUTH_URL)
wordpressOauthUrl = bundle.getString(WORDPRESS_OAUTH_URL) casLoginUrl = getString(CAS_LOGIN_URL)
casLoginUrl = bundle.getString(CAS_LOGIN_URL) casToken = getString(CAS_TOKEN)
casToken = bundle.getString(CAS_TOKEN) casServiceName = getString(CAS_SERVICE_NAME)
casServiceName = bundle.getString(CAS_SERVICE_NAME) casServiceNameTextColor = getInt(CAS_SERVICE_NAME_TEXT_COLOR)
casServiceNameTextColor = bundle.getInt(CAS_SERVICE_NAME_TEXT_COLOR) casServiceButtonColor = getInt(CAS_SERVICE_BUTTON_COLOR)
casServiceButtonColor = bundle.getInt(CAS_SERVICE_BUTTON_COLOR) customOauthUrl = getString(CUSTOM_OAUTH_URL)
customOauthUrl = bundle.getString(CUSTOM_OAUTH_URL) customOauthServiceName = getString(CUSTOM_OAUTH_SERVICE_NAME)
customOauthServiceName = bundle.getString(CUSTOM_OAUTH_SERVICE_NAME) customOauthServiceTextColor = getInt(CUSTOM_OAUTH_SERVICE_NAME_TEXT_COLOR)
customOauthServiceTextColor = bundle.getInt(CUSTOM_OAUTH_SERVICE_NAME_TEXT_COLOR) customOauthServiceButtonColor = getInt(CUSTOM_OAUTH_SERVICE_BUTTON_COLOR)
customOauthServiceButtonColor = bundle.getInt(CUSTOM_OAUTH_SERVICE_BUTTON_COLOR) samlUrl = getString(SAML_URL)
samlUrl = bundle.getString(SAML_URL) samlToken = getString(SAML_TOKEN)
samlToken = bundle.getString(SAML_TOKEN) samlServiceName = getString(SAML_SERVICE_NAME)
samlServiceName = bundle.getString(SAML_SERVICE_NAME) samlServiceTextColor = getInt(SAML_SERVICE_NAME_TEXT_COLOR)
samlServiceTextColor = bundle.getInt(SAML_SERVICE_NAME_TEXT_COLOR) samlServiceButtonColor = getInt(SAML_SERVICE_BUTTON_COLOR)
samlServiceButtonColor = bundle.getInt(SAML_SERVICE_BUTTON_COLOR) totalSocialAccountsEnabled = getInt(TOTAL_SOCIAL_ACCOUNTS)
totalSocialAccountsEnabled = bundle.getInt(TOTAL_SOCIAL_ACCOUNTS) isLoginFormEnabled = getBoolean(IS_LOGIN_FORM_ENABLED)
isLoginFormEnabled = bundle.getBoolean(IS_LOGIN_FORM_ENABLED) isNewAccountCreationEnabled = getBoolean(IS_NEW_ACCOUNT_CREATION_ENABLED)
isNewAccountCreationEnabled = bundle.getBoolean(IS_NEW_ACCOUNT_CREATION_ENABLED) deepLinkInfo = getParcelable(DEEP_LINK_INFO)
deepLinkInfo = bundle.getParcelable(DEEP_LINK_INFO)
} }
} }
...@@ -388,7 +385,7 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView { ...@@ -388,7 +385,7 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
} }
override fun setupExpandAccountsView() { override fun setupExpandAccountsView() {
ui { _ -> ui {
expand_more_accounts_container.isVisible = true expand_more_accounts_container.isVisible = true
var isAccountsCollapsed = true var isAccountsCollapsed = true
button_expand_collapse_accounts.setOnClickListener { button_expand_collapse_accounts.setOnClickListener {
...@@ -406,14 +403,14 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView { ...@@ -406,14 +403,14 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
} }
override fun showLoginWithEmailButton() { override fun showLoginWithEmailButton() {
ui { _ -> ui {
button_login_with_email.setOnClickListener { presenter.toLoginWithEmail() } button_login_with_email.setOnClickListener { presenter.toLoginWithEmail() }
button_login_with_email.isVisible = true button_login_with_email.isVisible = true
} }
} }
override fun showCreateNewAccountButton() { override fun showCreateNewAccountButton() {
ui { _ -> ui {
button_create_an_account.setOnClickListener { presenter.toCreateAccount() } button_create_an_account.setOnClickListener { presenter.toCreateAccount() }
button_create_an_account.isVisible = true button_create_an_account.isVisible = true
} }
......
...@@ -31,12 +31,10 @@ import javax.inject.Inject ...@@ -31,12 +31,10 @@ import javax.inject.Inject
private const val BUNDLE_USER_ID = "user_id" private const val BUNDLE_USER_ID = "user_id"
private const val BUNDLE_AUTH_TOKEN = "auth_token" private const val BUNDLE_AUTH_TOKEN = "auth_token"
fun newInstance(userId: String, authToken: String): Fragment { fun newInstance(userId: String, authToken: String): Fragment = RegisterUsernameFragment().apply {
return RegisterUsernameFragment().apply { arguments = Bundle(2).apply {
arguments = Bundle(2).apply { putString(BUNDLE_USER_ID, userId)
putString(BUNDLE_USER_ID, userId) putString(BUNDLE_AUTH_TOKEN, authToken)
putString(BUNDLE_AUTH_TOKEN, authToken)
}
} }
} }
...@@ -53,13 +51,10 @@ class RegisterUsernameFragment : Fragment(), RegisterUsernameView { ...@@ -53,13 +51,10 @@ class RegisterUsernameFragment : Fragment(), RegisterUsernameView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { userId = getString(BUNDLE_USER_ID, "")
userId = bundle.getString(BUNDLE_USER_ID) authToken = getString(BUNDLE_AUTH_TOKEN, "")
authToken = bundle.getString(BUNDLE_AUTH_TOKEN) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
...@@ -75,7 +75,7 @@ class SignupFragment : Fragment(), SignupView { ...@@ -75,7 +75,7 @@ class SignupFragment : Fragment(), SignupView {
} }
private fun setupOnClickListener() = private fun setupOnClickListener() =
ui { _ -> ui {
button_register.setOnClickListener { button_register.setOnClickListener {
presenter.signup( presenter.signup(
text_username.textContent, text_username.textContent,
......
...@@ -25,12 +25,10 @@ import io.reactivex.disposables.Disposable ...@@ -25,12 +25,10 @@ import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.fragment_authentication_two_fa.* import kotlinx.android.synthetic.main.fragment_authentication_two_fa.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(username: String, password: String): Fragment { fun newInstance(username: String, password: String): Fragment = TwoFAFragment().apply {
return TwoFAFragment().apply { arguments = Bundle(2).apply {
arguments = Bundle(2).apply { putString(BUNDLE_USERNAME, username)
putString(BUNDLE_USERNAME, username) putString(BUNDLE_PASSWORD, password)
putString(BUNDLE_PASSWORD, password)
}
} }
} }
...@@ -50,13 +48,10 @@ class TwoFAFragment : Fragment(), TwoFAView { ...@@ -50,13 +48,10 @@ class TwoFAFragment : Fragment(), TwoFAView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { username = getString(BUNDLE_USERNAME, "")
username = bundle.getString(BUNDLE_USERNAME) password = getString(BUNDLE_PASSWORD, "")
password = bundle.getString(BUNDLE_PASSWORD) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
package chat.rocket.android.chatdetails.adapter package chat.rocket.android.chatdetails.adapter
import android.content.Context import DrawableHelper
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
......
...@@ -11,9 +11,15 @@ import chat.rocket.android.util.extensions.inflate ...@@ -11,9 +11,15 @@ import chat.rocket.android.util.extensions.inflate
class ChatDetailsAdapter: RecyclerView.Adapter<OptionViewHolder>() { class ChatDetailsAdapter: RecyclerView.Adapter<OptionViewHolder>() {
private val options: MutableList<Option> = ArrayList() private val options: MutableList<Option> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder = OptionViewHolder(parent.inflate(R.layout.item_detail_option)) override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): OptionViewHolder = OptionViewHolder(parent.inflate(R.layout.item_detail_option))
override fun onBindViewHolder(holder: OptionViewHolder, position: Int) = holder.bindViews(OptionItemHolder(options[position])) override fun onBindViewHolder(
holder: OptionViewHolder,
position: Int
) = holder.bindViews(OptionItemHolder(options[position]))
override fun getItemCount(): Int = options.size override fun getItemCount(): Int = options.size
......
...@@ -32,14 +32,12 @@ fun newInstance( ...@@ -32,14 +32,12 @@ fun newInstance(
chatRoomType: String, chatRoomType: String,
isSubscribed: Boolean, isSubscribed: Boolean,
disableMenu: Boolean disableMenu: Boolean
): ChatDetailsFragment { ): ChatDetailsFragment = ChatDetailsFragment().apply {
return ChatDetailsFragment().apply { arguments = Bundle(4).apply {
arguments = Bundle(4).apply { putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId) putString(BUNDLE_CHAT_ROOM_TYPE, chatRoomType)
putString(BUNDLE_CHAT_ROOM_TYPE, chatRoomType) putBoolean(BUNDLE_IS_SUBSCRIBED, isSubscribed)
putBoolean(BUNDLE_IS_SUBSCRIBED, isSubscribed) putBoolean(BUNDLE_DISABLE_MENU, disableMenu)
putBoolean(BUNDLE_DISABLE_MENU, disableMenu)
}
} }
} }
...@@ -66,15 +64,13 @@ class ChatDetailsFragment : Fragment(), ChatDetailsView { ...@@ -66,15 +64,13 @@ class ChatDetailsFragment : Fragment(), ChatDetailsView {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments
if (bundle != null) { arguments?.run {
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID) chatRoomId = getString(BUNDLE_CHAT_ROOM_ID)
chatRoomType = bundle.getString(BUNDLE_CHAT_ROOM_TYPE) chatRoomType = getString(BUNDLE_CHAT_ROOM_TYPE)
isSubscribed = bundle.getBoolean(BUNDLE_IS_SUBSCRIBED) isSubscribed = getBoolean(BUNDLE_IS_SUBSCRIBED)
disableMenu = bundle.getBoolean(BUNDLE_DISABLE_MENU) disableMenu = getBoolean(BUNDLE_DISABLE_MENU)
} else { } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
...@@ -5,9 +5,10 @@ import androidx.lifecycle.ViewModelProvider ...@@ -5,9 +5,10 @@ import androidx.lifecycle.ViewModelProvider
import chat.rocket.android.db.ChatRoomDao import chat.rocket.android.db.ChatRoomDao
import javax.inject.Inject import javax.inject.Inject
class ChatDetailsViewModelFactory @Inject constructor(private val chatRoomDao: ChatRoomDao) : ViewModelProvider.NewInstanceFactory() { class ChatDetailsViewModelFactory @Inject constructor(
private val chatRoomDao: ChatRoomDao
) : ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>) = override fun <T : ViewModel?> create(modelClass: Class<T>) = ChatDetailsViewModel(chatRoomDao) as T
ChatDetailsViewModel(chatRoomDao) as T
} }
\ No newline at end of file
...@@ -12,7 +12,10 @@ import com.facebook.drawee.backends.pipeline.Fresco ...@@ -12,7 +12,10 @@ import com.facebook.drawee.backends.pipeline.Fresco
import kotlinx.android.synthetic.main.item_action_button.view.* import kotlinx.android.synthetic.main.item_action_button.view.*
import timber.log.Timber import timber.log.Timber
class ActionsListAdapter(actions: List<Action>, var actionAttachmentOnClickListener: ActionAttachmentOnClickListener) : RecyclerView.Adapter<ActionsListAdapter.ViewHolder>() { class ActionsListAdapter(
actions: List<Action>,
var actionAttachmentOnClickListener: ActionAttachmentOnClickListener
) : RecyclerView.Adapter<ActionsListAdapter.ViewHolder>() {
var actions: List<Action> = actions var actions: List<Action> = actions
...@@ -62,9 +65,7 @@ class ActionsListAdapter(actions: List<Action>, var actionAttachmentOnClickListe ...@@ -62,9 +65,7 @@ class ActionsListAdapter(actions: List<Action>, var actionAttachmentOnClickListe
return ViewHolder(view) return ViewHolder(view)
} }
override fun getItemCount(): Int { override fun getItemCount(): Int = actions.size
return actions.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val action = actions[position] val action = actions[position]
......
...@@ -76,13 +76,9 @@ class ChatRoomAdapter( ...@@ -76,13 +76,9 @@ class ChatRoomAdapter(
} }
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int = dataSet[position].viewType
return dataSet[position].viewType
}
override fun getItemCount(): Int { override fun getItemCount(): Int = dataSet.size
return dataSet.size
}
override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) { override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) {
if (holder !is MessageViewHolder) { if (holder !is MessageViewHolder) {
...@@ -174,12 +170,12 @@ class ChatRoomAdapter( ...@@ -174,12 +170,12 @@ class ChatRoomAdapter(
Timber.d("index: $index") Timber.d("index: $index")
if (index > -1) { if (index > -1) {
dataSet[index] = message dataSet[index] = message
dataSet.forEachIndexed { index, viewModel -> dataSet.forEachIndexed { ind, viewModel ->
if (viewModel.messageId == message.messageId) { if (viewModel.messageId == message.messageId) {
if (viewModel.nextDownStreamMessage == null) { if (viewModel.nextDownStreamMessage == null) {
viewModel.reactions = message.reactions viewModel.reactions = message.reactions
} }
notifyItemChanged(index) notifyItemChanged(ind)
} }
} }
// Delete message only if current is a system message update, i.e.: Message Removed // Delete message only if current is a system message update, i.e.: Message Removed
...@@ -258,10 +254,10 @@ class ChatRoomAdapter( ...@@ -258,10 +254,10 @@ class ChatRoomAdapter(
actionSelectListener?.editMessage(roomId, id, message.message) actionSelectListener?.editMessage(roomId, id, message.message)
} }
R.id.action_message_star -> { R.id.action_message_star -> {
actionSelectListener?.toogleStar(id, !item.isChecked) actionSelectListener?.toggleStar(id, !item.isChecked)
} }
R.id.action_message_unpin -> { R.id.action_message_unpin -> {
actionSelectListener?.tooglePin(id, !item.isChecked) actionSelectListener?.togglePin(id, !item.isChecked)
} }
R.id.action_message_delete -> { R.id.action_message_delete -> {
actionSelectListener?.deleteMessage(roomId, id) actionSelectListener?.deleteMessage(roomId, id)
...@@ -298,9 +294,9 @@ class ChatRoomAdapter( ...@@ -298,9 +294,9 @@ class ChatRoomAdapter(
fun editMessage(roomId: String, messageId: String, text: String) fun editMessage(roomId: String, messageId: String, text: String)
fun toogleStar(id: String, star: Boolean) fun toggleStar(id: String, star: Boolean)
fun tooglePin(id: String, pin: Boolean) fun togglePin(id: String, pin: Boolean)
fun deleteMessage(roomId: String, id: String) fun deleteMessage(roomId: String, id: String)
......
...@@ -24,8 +24,8 @@ class RoomSuggestionsAdapter : SuggestionsAdapter<RoomSuggestionsViewHolder>("#" ...@@ -24,8 +24,8 @@ class RoomSuggestionsAdapter : SuggestionsAdapter<RoomSuggestionsViewHolder>("#"
override fun bind(item: SuggestionModel, itemClickListener: SuggestionsAdapter.ItemClickListener?) { override fun bind(item: SuggestionModel, itemClickListener: SuggestionsAdapter.ItemClickListener?) {
item as ChatRoomSuggestionUiModel item as ChatRoomSuggestionUiModel
with(itemView) { with(itemView) {
val fullname = itemView.findViewById<TextView>(R.id.text_fullname) val fullname = findViewById<TextView>(R.id.text_fullname)
val name = itemView.findViewById<TextView>(R.id.text_name) val name = findViewById<TextView>(R.id.text_name)
name.text = item.name name.text = item.name
fullname.text = item.fullName fullname.text = item.fullName
setOnClickListener { setOnClickListener {
......
...@@ -8,15 +8,14 @@ import chat.rocket.android.util.extensions.content ...@@ -8,15 +8,14 @@ import chat.rocket.android.util.extensions.content
import chat.rocket.android.util.extensions.openTabbedUrl import chat.rocket.android.util.extensions.openTabbedUrl
import kotlinx.android.synthetic.main.message_url_preview.view.* import kotlinx.android.synthetic.main.message_url_preview.view.*
class UrlPreviewViewHolder(itemView: View, class UrlPreviewViewHolder(
listener: ActionsListener, itemView: View,
reactionListener: EmojiReactionListener? = null) listener: ActionsListener,
: BaseViewHolder<UrlPreviewUiModel>(itemView, listener, reactionListener) { reactionListener: EmojiReactionListener? = null
) : BaseViewHolder<UrlPreviewUiModel>(itemView, listener, reactionListener) {
init { init {
with(itemView) { setupActionMenu(itemView.url_preview_layout)
setupActionMenu(url_preview_layout)
}
} }
override fun bindViews(data: UrlPreviewUiModel) { override fun bindViews(data: UrlPreviewUiModel) {
......
...@@ -182,8 +182,8 @@ class ChatRoomPresenter @Inject constructor( ...@@ -182,8 +182,8 @@ class ChatRoomPresenter @Inject constructor(
chatRoomId?.let { chatRoomId?.let {
manager.addRoomChannel(it, roomChangesChannel) manager.addRoomChannel(it, roomChangesChannel)
for (room in roomChangesChannel) { for (room in roomChangesChannel) {
dbManager.getRoom(room.id)?.let { dbManager.getRoom(room.id)?.let { chatRoom ->
view.onRoomUpdated(roomMapper.map(chatRoom = it, showLastMessage = true)) view.onRoomUpdated(roomMapper.map(chatRoom = chatRoom, showLastMessage = true))
} }
} }
} }
...@@ -321,12 +321,13 @@ class ChatRoomPresenter @Inject constructor( ...@@ -321,12 +321,13 @@ class ChatRoomPresenter @Inject constructor(
if (messageId == null) { if (messageId == null) {
val id = UUID.randomUUID().toString() val id = UUID.randomUUID().toString()
val username = userHelper.username() val username = userHelper.username()
val user = userHelper.user()
val newMessage = Message( val newMessage = Message(
id = id, id = id,
roomId = chatRoomId, roomId = chatRoomId,
message = text, message = text,
timestamp = Instant.now().toEpochMilli(), timestamp = Instant.now().toEpochMilli(),
sender = SimpleUser(null, username, username), sender = SimpleUser(user?.id, user?.username ?: username, user?.name),
attachments = null, attachments = null,
avatar = currentServer.avatarUrl(username ?: ""), avatar = currentServer.avatarUrl(username ?: ""),
channels = null, channels = null,
...@@ -1073,7 +1074,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1073,7 +1074,7 @@ class ChatRoomPresenter @Inject constructor(
launchUI(strategy) { launchUI(strategy) {
try { try {
messagesRepository.getById(messageId)?.let { message -> messagesRepository.getById(messageId)?.let { message ->
getChatRoomAsync(message.roomId)?.let { chatRoom -> getChatRoomAsync(message.roomId)?.let {
val models = mapper.map(message) val models = mapper.map(message)
models.firstOrNull()?.permalink?.let { models.firstOrNull()?.permalink?.let {
view.copyToClipboard(it) view.copyToClipboard(it)
...@@ -1294,9 +1295,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1294,9 +1295,7 @@ class ChatRoomPresenter @Inject constructor(
* @param unfinishedMessage The unfinished message to save. * @param unfinishedMessage The unfinished message to save.
*/ */
fun saveDraftMessage(unfinishedMessage: String) { fun saveDraftMessage(unfinishedMessage: String) {
if (unfinishedMessage.isNotBlank()) { localRepository.save(draftKey, unfinishedMessage)
localRepository.save(draftKey, unfinishedMessage)
}
} }
fun clearDraftMessage() { fun clearDraftMessage() {
......
...@@ -31,18 +31,16 @@ fun Context.chatRoomIntent( ...@@ -31,18 +31,16 @@ fun Context.chatRoomIntent(
isCreator: Boolean = false, isCreator: Boolean = false,
isFavorite: Boolean = false, isFavorite: Boolean = false,
chatRoomMessage: String? = null chatRoomMessage: String? = null
): Intent { ): Intent = Intent(this, ChatRoomActivity::class.java).apply {
return Intent(this, ChatRoomActivity::class.java).apply { putExtra(INTENT_CHAT_ROOM_ID, chatRoomId)
putExtra(INTENT_CHAT_ROOM_ID, chatRoomId) putExtra(INTENT_CHAT_ROOM_NAME, chatRoomName)
putExtra(INTENT_CHAT_ROOM_NAME, chatRoomName) putExtra(INTENT_CHAT_ROOM_TYPE, chatRoomType)
putExtra(INTENT_CHAT_ROOM_TYPE, chatRoomType) putExtra(INTENT_CHAT_ROOM_IS_READ_ONLY, isReadOnly)
putExtra(INTENT_CHAT_ROOM_IS_READ_ONLY, isReadOnly) putExtra(INTENT_CHAT_ROOM_LAST_SEEN, chatRoomLastSeen)
putExtra(INTENT_CHAT_ROOM_LAST_SEEN, chatRoomLastSeen) putExtra(INTENT_CHAT_IS_SUBSCRIBED, isSubscribed)
putExtra(INTENT_CHAT_IS_SUBSCRIBED, isSubscribed) putExtra(INTENT_CHAT_ROOM_IS_CREATOR, isCreator)
putExtra(INTENT_CHAT_ROOM_IS_CREATOR, isCreator) putExtra(INTENT_CHAT_ROOM_IS_FAVORITE, isFavorite)
putExtra(INTENT_CHAT_ROOM_IS_FAVORITE, isFavorite) putExtra(INTENT_CHAT_ROOM_MESSAGE, chatRoomMessage)
putExtra(INTENT_CHAT_ROOM_MESSAGE, chatRoomMessage)
}
} }
private const val INTENT_CHAT_ROOM_ID = "chat_room_id" private const val INTENT_CHAT_ROOM_ID = "chat_room_id"
...@@ -81,42 +79,44 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector { ...@@ -81,42 +79,44 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
return return
} }
val chatRoomId = intent.getStringExtra(INTENT_CHAT_ROOM_ID) with(intent) {
requireNotNull(chatRoomId) { "no chat_room_id provided in Intent extras" } val chatRoomId = getStringExtra(INTENT_CHAT_ROOM_ID)
requireNotNull(chatRoomId) { "no chat_room_id provided in Intent extras" }
val chatRoomName = intent.getStringExtra(INTENT_CHAT_ROOM_NAME) val chatRoomName = getStringExtra(INTENT_CHAT_ROOM_NAME)
requireNotNull(chatRoomName) { "no chat_room_name provided in Intent extras" } requireNotNull(chatRoomName) { "no chat_room_name provided in Intent extras" }
val chatRoomType = intent.getStringExtra(INTENT_CHAT_ROOM_TYPE) val chatRoomType = getStringExtra(INTENT_CHAT_ROOM_TYPE)
requireNotNull(chatRoomType) { "no chat_room_type provided in Intent extras" } requireNotNull(chatRoomType) { "no chat_room_type provided in Intent extras" }
val isReadOnly = intent.getBooleanExtra(INTENT_CHAT_ROOM_IS_READ_ONLY, true) val isReadOnly = getBooleanExtra(INTENT_CHAT_ROOM_IS_READ_ONLY, true)
val isCreator = intent.getBooleanExtra(INTENT_CHAT_ROOM_IS_CREATOR, false) val isCreator = getBooleanExtra(INTENT_CHAT_ROOM_IS_CREATOR, false)
val isFavorite = intent.getBooleanExtra(INTENT_CHAT_ROOM_IS_FAVORITE, false) val isFavorite = getBooleanExtra(INTENT_CHAT_ROOM_IS_FAVORITE, false)
val chatRoomLastSeen = intent.getLongExtra(INTENT_CHAT_ROOM_LAST_SEEN, -1) val chatRoomLastSeen = getLongExtra(INTENT_CHAT_ROOM_LAST_SEEN, -1)
val isSubscribed = intent.getBooleanExtra(INTENT_CHAT_IS_SUBSCRIBED, true) val isSubscribed = getBooleanExtra(INTENT_CHAT_IS_SUBSCRIBED, true)
val chatRoomMessage = intent.getStringExtra(INTENT_CHAT_ROOM_MESSAGE) val chatRoomMessage = getStringExtra(INTENT_CHAT_ROOM_MESSAGE)
setupToolbar() setupToolbar()
if (supportFragmentManager.findFragmentByTag(TAG_CHAT_ROOM_FRAGMENT) == null) { if (supportFragmentManager.findFragmentByTag(TAG_CHAT_ROOM_FRAGMENT) == null) {
addFragment(TAG_CHAT_ROOM_FRAGMENT, R.id.fragment_container) { addFragment(TAG_CHAT_ROOM_FRAGMENT, R.id.fragment_container) {
newInstance( newInstance(
chatRoomId, chatRoomId,
chatRoomName, chatRoomName,
chatRoomType, chatRoomType,
isReadOnly, isReadOnly,
chatRoomLastSeen, chatRoomLastSeen,
isSubscribed, isSubscribed,
isCreator, isCreator,
isFavorite, isFavorite,
chatRoomMessage chatRoomMessage
) )
}
} }
} }
} }
......
...@@ -111,19 +111,17 @@ fun newInstance( ...@@ -111,19 +111,17 @@ fun newInstance(
isCreator: Boolean = false, isCreator: Boolean = false,
isFavorite: Boolean = false, isFavorite: Boolean = false,
chatRoomMessage: String? = null chatRoomMessage: String? = null
): Fragment { ): Fragment = ChatRoomFragment().apply {
return ChatRoomFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId) putString(BUNDLE_CHAT_ROOM_NAME, chatRoomName)
putString(BUNDLE_CHAT_ROOM_NAME, chatRoomName) putString(BUNDLE_CHAT_ROOM_TYPE, chatRoomType)
putString(BUNDLE_CHAT_ROOM_TYPE, chatRoomType) putBoolean(BUNDLE_IS_CHAT_ROOM_READ_ONLY, isReadOnly)
putBoolean(BUNDLE_IS_CHAT_ROOM_READ_ONLY, isReadOnly) putLong(BUNDLE_CHAT_ROOM_LAST_SEEN, chatRoomLastSeen)
putLong(BUNDLE_CHAT_ROOM_LAST_SEEN, chatRoomLastSeen) putBoolean(BUNDLE_CHAT_ROOM_IS_SUBSCRIBED, isSubscribed)
putBoolean(BUNDLE_CHAT_ROOM_IS_SUBSCRIBED, isSubscribed) putBoolean(BUNDLE_CHAT_ROOM_IS_CREATOR, isCreator)
putBoolean(BUNDLE_CHAT_ROOM_IS_CREATOR, isCreator) putBoolean(BUNDLE_CHAT_ROOM_IS_FAVORITE, isFavorite)
putBoolean(BUNDLE_CHAT_ROOM_IS_FAVORITE, isFavorite) putString(BUNDLE_CHAT_ROOM_MESSAGE, chatRoomMessage)
putString(BUNDLE_CHAT_ROOM_MESSAGE, chatRoomMessage)
}
} }
} }
...@@ -259,7 +257,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -259,7 +257,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_fab.hide() button_fab.hide()
newMessageCount = 0 newMessageCount = 0
} else { } else {
if (dy < 0 && !button_fab.isVisible) { if (dy < 0 && isAdded && !button_fab.isVisible) {
button_fab.show() button_fab.show()
if (newMessageCount != 0) text_count.isVisible = true if (newMessageCount != 0) text_count.isVisible = true
} }
...@@ -272,20 +270,17 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -272,20 +270,17 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
setHasOptionsMenu(true) setHasOptionsMenu(true)
val bundle = arguments arguments?.run {
if (bundle != null) { chatRoomId = getString(BUNDLE_CHAT_ROOM_ID, "")
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID) chatRoomName = getString(BUNDLE_CHAT_ROOM_NAME, "")
chatRoomName = bundle.getString(BUNDLE_CHAT_ROOM_NAME) chatRoomType = getString(BUNDLE_CHAT_ROOM_TYPE, "")
chatRoomType = bundle.getString(BUNDLE_CHAT_ROOM_TYPE) isReadOnly = getBoolean(BUNDLE_IS_CHAT_ROOM_READ_ONLY)
isReadOnly = bundle.getBoolean(BUNDLE_IS_CHAT_ROOM_READ_ONLY) isSubscribed = getBoolean(BUNDLE_CHAT_ROOM_IS_SUBSCRIBED)
isSubscribed = bundle.getBoolean(BUNDLE_CHAT_ROOM_IS_SUBSCRIBED) chatRoomLastSeen = getLong(BUNDLE_CHAT_ROOM_LAST_SEEN)
chatRoomLastSeen = bundle.getLong(BUNDLE_CHAT_ROOM_LAST_SEEN) isCreator = getBoolean(BUNDLE_CHAT_ROOM_IS_CREATOR)
isCreator = bundle.getBoolean(BUNDLE_CHAT_ROOM_IS_CREATOR) isFavorite = getBoolean(BUNDLE_CHAT_ROOM_IS_FAVORITE)
isFavorite = bundle.getBoolean(BUNDLE_CHAT_ROOM_IS_FAVORITE) chatRoomMessage = getString(BUNDLE_CHAT_ROOM_MESSAGE)
chatRoomMessage = bundle.getString(BUNDLE_CHAT_ROOM_MESSAGE) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
adapter = ChatRoomAdapter(chatRoomId, chatRoomType, chatRoomName, this, reactionListener = this, navigator = navigator) adapter = ChatRoomAdapter(chatRoomId, chatRoomType, chatRoomName, this, reactionListener = this, navigator = navigator)
} }
...@@ -758,21 +753,20 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -758,21 +753,20 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
ui { ui {
text_connection_status.fadeIn() text_connection_status.fadeIn()
handler.removeCallbacks(dismissStatus) handler.removeCallbacks(dismissStatus)
when (state) { text_connection_status.text = when (state) {
is State.Connected -> { is State.Connected -> {
text_connection_status.text = getString(R.string.status_connected)
handler.postDelayed(dismissStatus, 2000) handler.postDelayed(dismissStatus, 2000)
getString(R.string.status_connected)
}
is State.Disconnected -> getString(R.string.status_disconnected)
is State.Connecting -> getString(R.string.status_connecting)
is State.Authenticating -> getString(R.string.status_authenticating)
is State.Disconnecting -> getString(R.string.status_disconnecting)
is State.Waiting -> getString(R.string.status_waiting, state.seconds)
else -> {
handler.postDelayed(dismissStatus, 500)
""
} }
is State.Disconnected ->
text_connection_status.text = getString(R.string.status_disconnected)
is State.Connecting ->
text_connection_status.text = getString(R.string.status_connecting)
is State.Authenticating ->
text_connection_status.text = getString(R.string.status_authenticating)
is State.Disconnecting ->
text_connection_status.text = getString(R.string.status_disconnecting)
is State.Waiting ->
text_connection_status.text = getString(R.string.status_waiting, state.seconds)
} }
} }
} }
...@@ -1098,7 +1092,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -1098,7 +1092,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
presenter.editMessage(roomId, messageId, text) presenter.editMessage(roomId, messageId, text)
} }
override fun toogleStar(id: String, star: Boolean) { override fun toggleStar(id: String, star: Boolean) {
if (star) { if (star) {
presenter.starMessage(id) presenter.starMessage(id)
} else { } else {
...@@ -1106,7 +1100,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -1106,7 +1100,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
} }
override fun tooglePin(id: String, pin: Boolean) { override fun togglePin(id: String, pin: Boolean) {
if (pin) { if (pin) {
presenter.pinMessage(id) presenter.pinMessage(id)
} else { } else {
......
...@@ -44,11 +44,15 @@ private fun ChatRoomFragment.setupSearchMessageMenuItem(menu: Menu, context: Con ...@@ -44,11 +44,15 @@ private fun ChatRoomFragment.setupSearchMessageMenuItem(menu: Menu, context: Con
.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { .setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?): Boolean { override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
dismissEmojiKeyboard() dismissEmojiKeyboard()
removeFavoriteMenuItem(menu)
removeDetailMenuItem(menu)
return true return true
} }
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
dismissEmojiKeyboard() dismissEmojiKeyboard()
setupFavoriteMenuItem(menu)
setupDetailsMenuItem(menu)
return true return true
} }
}) })
...@@ -73,7 +77,6 @@ private fun stylizeSearchView(searchView: SearchView, context: Context) { ...@@ -73,7 +77,6 @@ private fun stylizeSearchView(searchView: SearchView, context: Context) {
private fun ChatRoomFragment.setupSearchViewTextListener(searchView: SearchView) { private fun ChatRoomFragment.setupSearchViewTextListener(searchView: SearchView) {
searchView.onQueryTextListener { searchView.onQueryTextListener {
// TODO: We use isSearchTermQueried to avoid querying when the search view is expanded but the user doesn't start typing. Check for a native solution.
if (it.isEmpty() && isSearchTermQueried) { if (it.isEmpty() && isSearchTermQueried) {
presenter.loadMessages(chatRoomId, chatRoomType, clearDataSet = true) presenter.loadMessages(chatRoomId, chatRoomType, clearDataSet = true)
} else if (it.isNotEmpty()) { } else if (it.isNotEmpty()) {
...@@ -105,10 +108,18 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) { ...@@ -105,10 +108,18 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) {
private fun ChatRoomFragment.setupDetailsMenuItem(menu: Menu) { private fun ChatRoomFragment.setupDetailsMenuItem(menu: Menu) {
menu.add( menu.add(
Menu.NONE, Menu.NONE,
MENU_ACTION_SHOW_DETAILS, MENU_ACTION_SHOW_DETAILS,
Menu.NONE, Menu.NONE,
R.string.title_channel_details R.string.title_channel_details
).setIcon(R.drawable.ic_info_outline_white_24dp) ).setIcon(R.drawable.ic_info_outline_white_24dp)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}
private fun removeFavoriteMenuItem(menu: Menu) {
menu.removeItem(MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT)
}
private fun removeDetailMenuItem(menu: Menu) {
menu.removeItem(MENU_ACTION_SHOW_DETAILS)
} }
\ No newline at end of file
...@@ -416,21 +416,19 @@ class UiModelMapper @Inject constructor( ...@@ -416,21 +416,19 @@ class UiModelMapper @Inject constructor(
return fullUrl return fullUrl
} }
private fun attachmentText(text: String?, attachment: Attachment?, context: Context): String? { private fun attachmentText(text: String?, attachment: Attachment?, context: Context): String? = attachment?.run {
return if (attachment != null) { with(context) {
when { when {
attachment.imageUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_photo) imageUrl.isNotNullNorEmpty() -> getString(R.string.msg_preview_photo)
attachment.videoUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_video) videoUrl.isNotNullNorEmpty() -> getString(R.string.msg_preview_video)
attachment.audioUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_audio) audioUrl.isNotNullNorEmpty() -> getString(R.string.msg_preview_audio)
attachment.titleLink.isNotNullNorEmpty() && titleLink.isNotNullNorEmpty() &&
attachment.type?.contentEquals("file") == true -> type?.contentEquals("file") == true ->
context.getString(R.string.msg_preview_file) getString(R.string.msg_preview_file)
else -> text else -> text
} }
} else {
text
} }
} } ?: text
private fun attachmentDescription(attachment: Attachment): String? { private fun attachmentDescription(attachment: Attachment): String? {
return attachment.description return attachment.description
...@@ -464,11 +462,9 @@ class UiModelMapper @Inject constructor( ...@@ -464,11 +462,9 @@ class UiModelMapper @Inject constructor(
subscriptionId = chatRoom.subscriptionId) subscriptionId = chatRoom.subscriptionId)
} }
private fun mapMessagePreview(message: Message): Message { private fun mapMessagePreview(message: Message): Message = when (message.isSystemMessage()) {
return when (message.isSystemMessage()) { false -> stripMessageQuotes(message)
false -> stripMessageQuotes(message) true -> message.copy(message = getSystemMessage(message).toString())
true -> message.copy(message = getSystemMessage(message).toString())
}
} }
private fun getReactions(message: Message): List<ReactionUiModel> { private fun getReactions(message: Message): List<ReactionUiModel> {
...@@ -535,37 +531,33 @@ class UiModelMapper @Inject constructor( ...@@ -535,37 +531,33 @@ class UiModelMapper @Inject constructor(
private fun getTime(timestamp: Long) = DateTimeHelper.getTime(DateTimeHelper.getLocalDateTime(timestamp)) private fun getTime(timestamp: Long) = DateTimeHelper.getTime(DateTimeHelper.getLocalDateTime(timestamp))
private fun getContent(message: Message): CharSequence { private fun getContent(message: Message): CharSequence = when (message.isSystemMessage()) {
return when (message.isSystemMessage()) { true -> getSystemMessage(message)
true -> getSystemMessage(message) false -> parser.render(message, currentUsername)
false -> parser.render(message, currentUsername)
}
} }
private fun getSystemMessage(message: Message): CharSequence { private fun getSystemMessage(message: Message): CharSequence {
val content = when (message.type) { val content = with(context) {
//TODO: Add implementation for Welcome type. when (message.type) {
is MessageType.MessageRemoved -> context.getString(R.string.message_removed) //TODO: Add implementation for Welcome type.
is MessageType.UserJoined -> context.getString(R.string.message_user_joined_channel) is MessageType.MessageRemoved -> getString(R.string.message_removed)
is MessageType.UserLeft -> context.getString(R.string.message_user_left) is MessageType.UserJoined -> getString(R.string.message_user_joined_channel)
is MessageType.UserAdded -> context.getString(R.string.message_user_added_by, message.message, message.sender?.username) is MessageType.UserLeft -> getString(R.string.message_user_left)
is MessageType.RoomNameChanged -> context.getString(R.string.message_room_name_changed, message.message, message.sender?.username) is MessageType.UserAdded -> getString(R.string.message_user_added_by, message.message, message.sender?.username)
is MessageType.UserRemoved -> context.getString(R.string.message_user_removed_by, message.message, message.sender?.username) is MessageType.RoomNameChanged -> getString(R.string.message_room_name_changed, message.message, message.sender?.username)
is MessageType.MessagePinned -> context.getString(R.string.message_pinned) is MessageType.UserRemoved -> getString(R.string.message_user_removed_by, message.message, message.sender?.username)
is MessageType.UserMuted -> context.getString(R.string.message_muted, message.message, message.sender?.username) is MessageType.MessagePinned -> getString(R.string.message_pinned)
is MessageType.UserUnMuted -> context.getString(R.string.message_unmuted, message.message, message.sender?.username) is MessageType.UserMuted -> getString(R.string.message_muted, message.message, message.sender?.username)
is MessageType.SubscriptionRoleAdded -> context.getString(R.string.message_role_add, message.message, message.role, message.sender?.username) is MessageType.UserUnMuted -> getString(R.string.message_unmuted, message.message, message.sender?.username)
is MessageType.SubscriptionRoleRemoved -> context.getString(R.string.message_role_removed, message.message, message.role, message.sender?.username) is MessageType.SubscriptionRoleAdded -> getString(R.string.message_role_add, message.message, message.role, message.sender?.username)
is MessageType.RoomChangedPrivacy -> context.getString(R.string.message_room_changed_privacy, message.message, message.sender?.username) is MessageType.SubscriptionRoleRemoved -> getString(R.string.message_role_removed, message.message, message.role, message.sender?.username)
else -> { is MessageType.RoomChangedPrivacy -> getString(R.string.message_room_changed_privacy, message.message, message.sender?.username)
throw InvalidParameterException("Invalid message type: ${message.type}") else -> throw InvalidParameterException("Invalid message type: ${message.type}")
} }
} }
val spannableMsg = SpannableStringBuilder(content) val spannableMsg = SpannableStringBuilder(content)
spannableMsg.setSpan(StyleSpan(Typeface.ITALIC), 0, spannableMsg.length, spannableMsg.setSpan(StyleSpan(Typeface.ITALIC), 0, spannableMsg.length, 0)
0) spannableMsg.setSpan(ForegroundColorSpan(Color.GRAY), 0, spannableMsg.length, 0)
spannableMsg.setSpan(ForegroundColorSpan(Color.GRAY), 0, spannableMsg.length,
0)
return spannableMsg return spannableMsg
} }
......
...@@ -36,14 +36,29 @@ class RoomUiModelMapper( ...@@ -36,14 +36,29 @@ class RoomUiModelMapper(
grouped: Boolean = false, grouped: Boolean = false,
showLastMessage: Boolean = true showLastMessage: Boolean = true
): List<ItemHolder<*>> { ): List<ItemHolder<*>> {
val list = ArrayList<ItemHolder<*>>(rooms.size + 4) val list = ArrayList<ItemHolder<*>>(rooms.size + 5)
var lastType: String? = null var lastType: String? = null
rooms.forEach { room -> if (grouped) {
if (grouped && lastType != room.chatRoom.type) { val favRooms = rooms.filter { it.chatRoom.favorite == true }
list.add(HeaderItemHolder(roomType(room.chatRoom.type))) val unfavRooms = rooms.filterNot { it.chatRoom.favorite == true }
if (favRooms.isNotEmpty()) {
list.add(HeaderItemHolder(context.resources.getString(R.string.header_favorite)))
}
favRooms.forEach { room ->
list.add(RoomItemHolder(map(room, showLastMessage)))
}
unfavRooms.forEach { room ->
if (lastType != room.chatRoom.type) {
list.add(HeaderItemHolder(roomType(room.chatRoom.type)))
}
list.add(RoomItemHolder(map(room, showLastMessage)))
lastType = room.chatRoom.type
}
} else {
rooms.forEach { room ->
list.add(RoomItemHolder(map(room, showLastMessage)))
} }
list.add(RoomItemHolder(map(room, showLastMessage)))
lastType = room.chatRoom.type
} }
return list return list
...@@ -62,76 +77,71 @@ class RoomUiModelMapper( ...@@ -62,76 +77,71 @@ class RoomUiModelMapper(
return list return list
} }
private fun mapUser(user: User): RoomUiModel { private fun mapUser(user: User): RoomUiModel = with(user) {
return with(user) { val name = mapName(user.username!!, user.name)
val name = mapName(user.username!!, user.name) val status = user.status
val status = user.status val avatar = serverUrl.avatarUrl(user.username!!)
val avatar = serverUrl.avatarUrl(user.username!!) val username = user.username!!
val username = user.username!!
RoomUiModel( RoomUiModel(
id = user.id, id = user.id,
name = name, name = name,
type = roomTypeOf(RoomType.DIRECT_MESSAGE), type = roomTypeOf(RoomType.DIRECT_MESSAGE),
avatar = avatar, avatar = avatar,
status = status, status = status,
username = username username = username
) )
}
} }
private fun mapRoom(room: Room, showLastMessage: Boolean = true): RoomUiModel { private fun mapRoom(room: Room, showLastMessage: Boolean = true): RoomUiModel = with(room) {
return with(room) { RoomUiModel(
RoomUiModel(
id = id, id = id,
name = name!!, name = name!!,
type = type, type = type,
avatar = serverUrl.avatarUrl(name!!, isGroupOrChannel = true), avatar = serverUrl.avatarUrl(name!!, isGroupOrChannel = true),
lastMessage = if (showLastMessage) { lastMessage = if (showLastMessage) {
mapLastMessage( mapLastMessage(
lastMessage?.sender?.id, lastMessage?.sender?.username, lastMessage?.sender?.id, lastMessage?.sender?.username,
lastMessage?.sender?.name, lastMessage?.message, lastMessage?.sender?.name, lastMessage?.message,
isDirectMessage = type is RoomType.DirectMessage isDirectMessage = type is RoomType.DirectMessage
) )
} else { } else {
null null
}, },
muted = muted.orEmpty(), muted = muted.orEmpty(),
writable = isChannelWritable(muted) writable = isChannelWritable(muted)
) )
}
} }
fun map(chatRoom: ChatRoom, showLastMessage: Boolean = true): RoomUiModel { fun map(chatRoom: ChatRoom, showLastMessage: Boolean = true): RoomUiModel = with(chatRoom.chatRoom) {
return with(chatRoom.chatRoom) { val isUnread = alert || unread > 0
val isUnread = alert || unread > 0 val type = roomTypeOf(type)
val type = roomTypeOf(type) val status = chatRoom.status?.let { userStatusOf(it) }
val status = chatRoom.status?.let { userStatusOf(it) } val roomName = mapName(name, fullname)
val roomName = mapName(name, fullname) val favorite = favorite
val timestamp = mapDate(lastMessageTimestamp ?: updatedAt) val timestamp = mapDate(lastMessageTimestamp ?: updatedAt)
val avatar = if (type is RoomType.DirectMessage) { val avatar = if (type is RoomType.DirectMessage) {
serverUrl.avatarUrl(name) serverUrl.avatarUrl(name)
} else { } else {
serverUrl.avatarUrl(name, isGroupOrChannel = true) serverUrl.avatarUrl(name, isGroupOrChannel = true)
} }
val unread = mapUnread(unread) val unread = mapUnread(unread)
val lastMessage = if (showLastMessage) { val lastMessage = if (showLastMessage) {
mapLastMessage( mapLastMessage(
lastMessageUserId, lastMessageUserId,
chatRoom.lastMessageUserName, chatRoom.lastMessageUserName,
chatRoom.lastMessageUserFullName, chatRoom.lastMessageUserFullName,
lastMessageText, lastMessageText,
type is RoomType.DirectMessage type is RoomType.DirectMessage
) )
} else { } else {
null null
} }
val hasMentions = mapMentions(userMentions, groupMentions) val hasMentions = mapMentions(userMentions, groupMentions)
val open = open val open = open
val lastMessageMarkdown = val lastMessageMarkdown = lastMessage?.let { Markwon.markdown(context, it.toString()).toString() }
lastMessage?.let { Markwon.markdown(context, it.toString()).toString() }
RoomUiModel( RoomUiModel(
id = id, id = id,
name = roomName, name = roomName,
type = type, type = type,
...@@ -140,14 +150,14 @@ class RoomUiModelMapper( ...@@ -140,14 +150,14 @@ class RoomUiModelMapper(
date = timestamp, date = timestamp,
unread = unread, unread = unread,
mentions = hasMentions, mentions = hasMentions,
favorite = favorite,
alert = isUnread, alert = isUnread,
lastMessage = lastMessageMarkdown, lastMessage = lastMessageMarkdown,
status = status, status = status,
username = if (type is RoomType.DirectMessage) name else null, username = if (type is RoomType.DirectMessage) name else null,
muted = muted.orEmpty(), muted = muted.orEmpty(),
writable = isChannelWritable(muted) writable = isChannelWritable(muted)
) )
}
} }
private fun isChannelWritable(muted: List<String>?): Boolean { private fun isChannelWritable(muted: List<String>?): Boolean {
...@@ -155,14 +165,13 @@ class RoomUiModelMapper( ...@@ -155,14 +165,13 @@ class RoomUiModelMapper(
return canWriteToReadOnlyChannels || !muted.orEmpty().contains(currentUser?.username) return canWriteToReadOnlyChannels || !muted.orEmpty().contains(currentUser?.username)
} }
private fun roomType(type: String): String { private fun roomType(type: String): String = with(context.resources) {
val resources = context.resources when (type) {
return when (type) { RoomType.CHANNEL -> getString(R.string.header_channel)
RoomType.CHANNEL -> resources.getString(R.string.header_channel) RoomType.PRIVATE_GROUP -> getString(R.string.header_private_groups)
RoomType.PRIVATE_GROUP -> resources.getString(R.string.header_private_groups) RoomType.DIRECT_MESSAGE -> getString(R.string.header_direct_messages)
RoomType.DIRECT_MESSAGE -> resources.getString(R.string.header_direct_messages) RoomType.LIVECHAT -> getString(R.string.header_live_chats)
RoomType.LIVECHAT -> resources.getString(R.string.header_live_chats) else -> getString(R.string.header_unknown)
else -> resources.getString(R.string.header_unknown)
} }
} }
...@@ -195,13 +204,11 @@ class RoomUiModelMapper( ...@@ -195,13 +204,11 @@ class RoomUiModelMapper(
} }
} }
private fun mapUnread(unread: Long): String? { private fun mapUnread(unread: Long): String? = when (unread) {
return when (unread) { 0L -> null
0L -> null in 1..99 -> unread.toString()
in 1..99 -> unread.toString() else -> context.getString(R.string.msg_more_than_ninety_nine_unread_messages)
else -> context.getString(R.string.msg_more_than_ninety_nine_unread_messages)
}
} }
private fun mapMentions(userMentions: Long?, groupMentions: Long?): Boolean { private fun mapMentions(userMentions: Long?, groupMentions: Long?): Boolean {
......
...@@ -8,6 +8,7 @@ import androidx.core.view.isInvisible ...@@ -8,6 +8,7 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.model.RoomUiModel import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import chat.rocket.android.util.extension.setTextViewAppearance
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import kotlinx.android.synthetic.main.item_chat.view.* import kotlinx.android.synthetic.main.item_chat.view.*
...@@ -16,12 +17,12 @@ import kotlinx.android.synthetic.main.unread_messages_badge.view.* ...@@ -16,12 +17,12 @@ import kotlinx.android.synthetic.main.unread_messages_badge.view.*
class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit) : class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit) :
ViewHolder<RoomItemHolder>(itemView) { ViewHolder<RoomItemHolder>(itemView) {
private val resources: Resources = itemView.resources private val resources: Resources = itemView.resources
private val channelIcon: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp) private val channelIcon: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp, null)
private val groupIcon: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp) private val groupIcon: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp, null)
private val onlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp) private val onlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp, null)
private val awayIcon: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp) private val awayIcon: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp, null)
private val busyIcon: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp) private val busyIcon: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp, null)
private val offlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp) private val offlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp, null)
override fun bindViews(data: RoomItemHolder) { override fun bindViews(data: RoomItemHolder) {
val room = data.data val room = data.data
...@@ -53,14 +54,14 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit ...@@ -53,14 +54,14 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit
if (room.unread == null) text_total_unread_messages.text = "!" if (room.unread == null) text_total_unread_messages.text = "!"
if (room.unread != null) text_total_unread_messages.text = room.unread if (room.unread != null) text_total_unread_messages.text = room.unread
if (room.mentions) text_total_unread_messages.text = "@${room.unread}" if (room.mentions) text_total_unread_messages.text = "@${room.unread}"
text_chat_name.setTextAppearance(context, R.style.ChatList_ChatName_Unread_TextView) text_chat_name.setTextViewAppearance(context, R.style.ChatList_ChatName_Unread_TextView)
text_timestamp.setTextAppearance(context, R.style.ChatList_Timestamp_Unread_TextView) text_timestamp.setTextViewAppearance(context, R.style.ChatList_Timestamp_Unread_TextView)
text_last_message.setTextAppearance(context, R.style.ChatList_LastMessage_Unread_TextView) text_last_message.setTextViewAppearance(context, R.style.ChatList_LastMessage_Unread_TextView)
text_total_unread_messages.isVisible = true text_total_unread_messages.isVisible = true
} else { } else {
text_chat_name.setTextAppearance(context, R.style.ChatList_ChatName_TextView) text_chat_name.setTextViewAppearance(context, R.style.ChatList_ChatName_TextView)
text_timestamp.setTextAppearance(context, R.style.ChatList_Timestamp_TextView) text_timestamp.setTextViewAppearance(context, R.style.ChatList_Timestamp_TextView)
text_last_message.setTextAppearance(context, R.style.ChatList_LastMessage_TextView) text_last_message.setTextViewAppearance(context, R.style.ChatList_LastMessage_TextView)
text_total_unread_messages.isInvisible = true text_total_unread_messages.isInvisible = true
} }
...@@ -68,20 +69,16 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit ...@@ -68,20 +69,16 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit
} }
} }
private fun getRoomDrawable(type: RoomType): Drawable? { private fun getRoomDrawable(type: RoomType): Drawable? = when (type) {
return when (type) { is RoomType.Channel -> channelIcon
is RoomType.Channel -> channelIcon is RoomType.PrivateGroup -> groupIcon
is RoomType.PrivateGroup -> groupIcon else -> null
else -> null
}
} }
private fun getStatusDrawable(status: UserStatus): Drawable { private fun getStatusDrawable(status: UserStatus): Drawable = when (status) {
return when (status) { is UserStatus.Online -> onlineIcon
is UserStatus.Online -> onlineIcon is UserStatus.Away -> awayIcon
is UserStatus.Away -> awayIcon is UserStatus.Busy -> busyIcon
is UserStatus.Busy -> busyIcon else -> offlineIcon
else -> offlineIcon
}
} }
} }
\ No newline at end of file
...@@ -19,22 +19,20 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : ...@@ -19,22 +19,20 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) :
notifyDataSetChanged() notifyDataSetChanged()
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<*> { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<*> = when (viewType) {
return when (viewType) { VIEW_TYPE_ROOM -> {
VIEW_TYPE_ROOM -> { val view = parent.inflate(R.layout.item_chat)
val view = parent.inflate(R.layout.item_chat) RoomViewHolder(view, listener)
RoomViewHolder(view, listener) }
} VIEW_TYPE_HEADER -> {
VIEW_TYPE_HEADER -> { val view = parent.inflate(R.layout.item_chatroom_header)
val view = parent.inflate(R.layout.item_chatroom_header) HeaderViewHolder(view)
HeaderViewHolder(view) }
} VIEW_TYPE_LOADING -> {
VIEW_TYPE_LOADING -> { val view = parent.inflate(R.layout.item_loading)
val view = parent.inflate(R.layout.item_loading) LoadingViewHolder(view)
LoadingViewHolder(view)
}
else -> throw IllegalStateException("View type must be either Room, Header or Loading")
} }
else -> throw IllegalStateException("View type must be either Room, Header or Loading")
} }
override fun getItemCount() = values.size override fun getItemCount() = values.size
...@@ -49,13 +47,11 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : ...@@ -49,13 +47,11 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) :
} }
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int = when (values[position]) {
return when (values[position]) { is RoomItemHolder -> VIEW_TYPE_ROOM
is RoomItemHolder -> VIEW_TYPE_ROOM is HeaderItemHolder -> VIEW_TYPE_HEADER
is HeaderItemHolder -> VIEW_TYPE_HEADER is LoadingItemHolder -> VIEW_TYPE_LOADING
is LoadingItemHolder -> VIEW_TYPE_LOADING else -> throw IllegalStateException("View type must be either Room, Header or Loading")
else -> throw IllegalStateException("View type must be either Room, Header or Loading")
}
} }
override fun onBindViewHolder(holder: ViewHolder<*>, position: Int) { override fun onBindViewHolder(holder: ViewHolder<*>, position: Int) {
......
...@@ -12,6 +12,7 @@ data class RoomUiModel( ...@@ -12,6 +12,7 @@ data class RoomUiModel(
val date: CharSequence? = null, val date: CharSequence? = null,
val unread: String? = null, val unread: String? = null,
val alert: Boolean = false, val alert: Boolean = false,
val favorite: Boolean? = false,
val mentions: Boolean = false, val mentions: Boolean = false,
val lastMessage: CharSequence? = null, val lastMessage: CharSequence? = null,
val status: UserStatus? = null, val status: UserStatus? = null,
......
...@@ -36,7 +36,6 @@ import chat.rocket.android.helper.SharedPreferenceHelper ...@@ -36,7 +36,6 @@ import chat.rocket.android.helper.SharedPreferenceHelper
import chat.rocket.android.util.extension.onQueryTextListener import chat.rocket.android.util.extension.onQueryTextListener
import chat.rocket.android.util.extensions.fadeIn import chat.rocket.android.util.extensions.fadeIn
import chat.rocket.android.util.extensions.fadeOut import chat.rocket.android.util.extensions.fadeOut
import chat.rocket.android.util.extensions.ifNotNullNorEmpty
import chat.rocket.android.util.extensions.ifNotNullNotEmpty import chat.rocket.android.util.extensions.ifNotNullNotEmpty
import chat.rocket.android.util.extensions.inflate import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast import chat.rocket.android.util.extensions.showToast
...@@ -69,11 +68,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -69,11 +68,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
private var progressDialog: ProgressDialog? = null private var progressDialog: ProgressDialog? = null
companion object { companion object {
fun newInstance(chatRoomId: String? = null): ChatRoomsFragment { fun newInstance(chatRoomId: String? = null): ChatRoomsFragment = ChatRoomsFragment().apply {
return ChatRoomsFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
}
} }
} }
} }
...@@ -82,9 +79,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -82,9 +79,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
setHasOptionsMenu(true) setHasOptionsMenu(true)
val bundle = arguments arguments?.run {
if (bundle != null) { chatRoomId = getString(BUNDLE_CHAT_ROOM_ID)
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID)
chatRoomId.ifNotNullNotEmpty { roomId -> chatRoomId.ifNotNullNotEmpty { roomId ->
presenter.loadChatRoom(roomId) presenter.loadChatRoom(roomId)
chatRoomId = null chatRoomId = null
...@@ -129,12 +125,14 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -129,12 +125,14 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
) )
) )
recycler_view.itemAnimator = DefaultItemAnimator() recycler_view.itemAnimator = DefaultItemAnimator()
recycler_view.adapter = adapter
viewModel.getChatRooms().observe(viewLifecycleOwner, Observer { rooms -> viewModel.getChatRooms().observe(viewLifecycleOwner, Observer { rooms ->
rooms?.let { rooms?.let {
Timber.d("Got items: $it") Timber.d("Got items: $it")
adapter.values = it adapter.values = it
if (recycler_view.adapter != adapter) {
recycler_view.adapter = adapter
}
if (rooms.isNotEmpty()) { if (rooms.isNotEmpty()) {
text_no_data_to_display.isVisible = false text_no_data_to_display.isVisible = false
} }
...@@ -320,21 +318,20 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -320,21 +318,20 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
ui { ui {
text_connection_status.fadeIn() text_connection_status.fadeIn()
handler.removeCallbacks(dismissStatus) handler.removeCallbacks(dismissStatus)
when (state) { text_connection_status.text = when (state) {
is State.Connected -> { is State.Connected -> {
text_connection_status.text = getString(R.string.status_connected)
handler.postDelayed(dismissStatus, 2000) handler.postDelayed(dismissStatus, 2000)
getString(R.string.status_connected)
}
is State.Disconnected -> getString(R.string.status_disconnected)
is State.Connecting -> getString(R.string.status_connecting)
is State.Authenticating -> getString(R.string.status_authenticating)
is State.Disconnecting -> getString(R.string.status_disconnecting)
is State.Waiting -> getString(R.string.status_waiting, state.seconds)
else -> {
handler.postDelayed(dismissStatus, 500)
""
} }
is State.Disconnected -> text_connection_status.text =
getString(R.string.status_disconnected)
is State.Connecting -> text_connection_status.text =
getString(R.string.status_connecting)
is State.Authenticating -> text_connection_status.text =
getString(R.string.status_authenticating)
is State.Disconnecting -> text_connection_status.text =
getString(R.string.status_disconnecting)
is State.Waiting -> text_connection_status.text =
getString(R.string.status_waiting, state.seconds)
} }
} }
} }
......
...@@ -45,9 +45,7 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback ...@@ -45,9 +45,7 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback
lateinit var analyticsManager: AnalyticsManager lateinit var analyticsManager: AnalyticsManager
private var actionMode: ActionMode? = null private var actionMode: ActionMode? = null
private val adapter: MembersAdapter = MembersAdapter { private val adapter: MembersAdapter = MembersAdapter {
if (it.username != null) { it.username?.run { processSelectedMember(this) }
processSelectedMember(it.username)
}
} }
private val compositeDisposable = CompositeDisposable() private val compositeDisposable = CompositeDisposable()
private var channelType: String = RoomType.CHANNEL private var channelType: String = RoomType.CHANNEL
...@@ -294,8 +292,8 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback ...@@ -294,8 +292,8 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback
private fun addChip(chipText: String) { private fun addChip(chipText: String) {
val chip = Chip(context) val chip = Chip(context)
chip.chipText = chipText chip.text = chipText
chip.isCloseIconEnabled = true chip.isCloseIconVisible = true
chip.setChipBackgroundColorResource(R.color.icon_grey) chip.setChipBackgroundColorResource(R.color.icon_grey)
setupChipOnCloseIconClickListener(chip) setupChipOnCloseIconClickListener(chip)
chip_group_member.addView(chip) chip_group_member.addView(chip)
...@@ -304,7 +302,7 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback ...@@ -304,7 +302,7 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback
private fun setupChipOnCloseIconClickListener(chip: Chip) { private fun setupChipOnCloseIconClickListener(chip: Chip) {
chip.setOnCloseIconClickListener { chip.setOnCloseIconClickListener {
removeChip(it) removeChip(it)
removeMember((it as Chip).chipText.toString()) removeMember((it as Chip).text.toString())
// whenever we remove a chip we should process the chip group visibility. // whenever we remove a chip we should process the chip group visibility.
processChipGroupVisibility() processChipGroupVisibility()
} }
......
...@@ -40,6 +40,12 @@ import kotlinx.coroutines.experimental.newSingleThreadContext ...@@ -40,6 +40,12 @@ import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.withContext import kotlinx.coroutines.experimental.withContext
import timber.log.Timber import timber.log.Timber
import java.util.HashSet import java.util.HashSet
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.collections.LinkedHashMap
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
class DatabaseManager(val context: Application, val serverUrl: String) { class DatabaseManager(val context: Application, val serverUrl: String) {
...@@ -140,7 +146,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -140,7 +146,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
batch.forEach { batch.forEach {
when (it.type) { when (it.type) {
is Type.Removed -> toRemove.add(removeChatRoom(it.data)) is Type.Removed -> toRemove.add(removeChatRoom(it.data))
is Type.Inserted -> insertChatRoom(it.data)?.let { toInsert.add(it) } is Type.Inserted -> insertChatRoom(it.data)?.let { room -> toInsert.add(room) }
is Type.Updated -> { is Type.Updated -> {
when (it.data) { when (it.data) {
is Subscription -> updateSubs[(it.data as Subscription).roomId] = it.data as Subscription is Subscription -> updateSubs[(it.data as Subscription).roomId] = it.data as Subscription
...@@ -186,16 +192,14 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -186,16 +192,14 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
} }
} }
fun processMessagesBatch(messages: List<Message>): Job { fun processMessagesBatch(messages: List<Message>): Job = launch(dbManagerContext) {
return launch(dbManagerContext) { val list = mutableListOf<Pair<MessageEntity, List<BaseMessageEntity>>>()
val list = mutableListOf<Pair<MessageEntity, List<BaseMessageEntity>>>() messages.forEach { message ->
messages.forEach { message -> val pair = createMessageEntities(message)
val pair = createMessageEntities(message) list.add(pair)
list.add(pair)
}
sendOperation(Operation.InsertMessages(list))
} }
sendOperation(Operation.InsertMessages(list))
} }
private suspend fun createMessageEntities(message: Message): Pair<MessageEntity, List<BaseMessageEntity>> { private suspend fun createMessageEntities(message: Message): Pair<MessageEntity, List<BaseMessageEntity>> {
...@@ -213,91 +217,70 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -213,91 +217,70 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
return Pair(messageEntity, list) return Pair(messageEntity, list)
} }
private fun createReactions(message: Message): List<BaseMessageEntity>? { private fun createReactions(message: Message): List<BaseMessageEntity>? = message.reactions?.run {
if (message.reactions == null || message.reactions!!.isEmpty()) { if (isNotEmpty()) {
return null val list = mutableListOf<BaseMessageEntity>()
} keys.forEach { reaction ->
get(reaction)?.let { reactionValue ->
val reactions = message.reactions!! list.add(ReactionEntity(reaction, message.id, size, reactionValue.joinToString()))
}
val list = mutableListOf<BaseMessageEntity>()
reactions.keys.forEach { reaction ->
val users = reactions[reaction]
users?.let { users ->
list.add(ReactionEntity(reaction, message.id, users.size, users.joinToString()))
} }
} list
} else null
return list
} }
private fun createUrlEntities(message: Message): List<BaseMessageEntity>? { private fun createUrlEntities(message: Message): List<BaseMessageEntity>? = message.urls?.run {
if (message.urls == null || message.urls!!.isEmpty()) { if (isNotEmpty()) {
return null val list = mutableListOf<UrlEntity>()
} forEach { url ->
list.add(UrlEntity(message.id, url.url, url.parsedUrl?.host, url.meta?.title,
val list = mutableListOf<UrlEntity>() url.meta?.description, url.meta?.imageUrl))
message.urls!!.forEach { url -> }
list.add(UrlEntity(message.id, url.url, url.parsedUrl?.host, url.meta?.title, list
url.meta?.description, url.meta?.imageUrl)) } else null
}
return list
} }
private fun createChannelRelations(message: Message): List<BaseMessageEntity>? { private fun createChannelRelations(message: Message): List<BaseMessageEntity>? = message.channels?.run {
if (message.channels == null || message.channels!!.isEmpty()) { if (isNotEmpty()) {
return null val list = mutableListOf<MessageChannels>()
} forEach { channel ->
list.add(MessageChannels(message.id, channel.id, channel.name))
val list = mutableListOf<MessageChannels>() }
message.channels!!.forEach { channel -> list
list.add(MessageChannels(message.id, channel.id, channel.name)) } else null
}
return list
} }
private suspend fun createMentionRelations(message: Message): List<BaseMessageEntity>? { private suspend fun createMentionRelations(message: Message): List<BaseMessageEntity>? = message.mentions?.run {
if (message.mentions == null || message.mentions!!.isEmpty()) { if (isNotEmpty()) {
return null val list = mutableListOf<MessageMentionsRelation>()
} filterNot { user -> user.id.isNullOrEmpty() }.forEach { mention ->
insertUserIfMissing(mention)
val list = mutableListOf<MessageMentionsRelation>() list.add(MessageMentionsRelation(message.id, mention.id!!))
message.mentions!!.filterNot { user -> user.id.isNullOrEmpty() }.forEach { mention -> }
insertUserIfMissing(mention) list
list.add(MessageMentionsRelation(message.id, mention.id!!)) } else null
}
return list
} }
private suspend fun createFavoriteRelations(message: Message): List<BaseMessageEntity>? { private suspend fun createFavoriteRelations(message: Message): List<BaseMessageEntity>? = message.starred?.run {
if (message.starred == null || message.starred!!.isEmpty()) { if (isNotEmpty()) {
return null val list = mutableListOf<MessageFavoritesRelation>()
} filterNot { user -> user.id.isNullOrEmpty() }.forEach { userId ->
insertUserIfMissing(userId)
val list = mutableListOf<MessageFavoritesRelation>() list.add(MessageFavoritesRelation(message.id, userId.id!!))
message.starred!!.filterNot { user -> user.id.isNullOrEmpty() }.forEach { userId -> }
insertUserIfMissing(userId) list
list.add(MessageFavoritesRelation(message.id, userId.id!!)) } else null
}
return list
} }
private fun createAttachments(message: Message): List<BaseMessageEntity>? {
if (message.attachments == null || message.attachments!!.isEmpty()) {
return null
}
val list = ArrayList<BaseMessageEntity>(message.attachments!!.size)
message.attachments!!.forEach { attachment -> private fun createAttachments(message: Message): List<BaseMessageEntity>? = message.attachments?.run {
list.addAll(attachment.asEntity(message.id, context)) if (isNotEmpty()) {
} val list = ArrayList<BaseMessageEntity>(size)
forEach { attachment ->
return list list.addAll(attachment.asEntity(message.id, context))
}
list
} else null
} }
private suspend fun createUpdates(): List<ChatRoomEntity> { private suspend fun createUpdates(): List<ChatRoomEntity> {
...@@ -375,20 +358,15 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -375,20 +358,15 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
} }
} }
private fun mapLastMessageText(message: Message?): String? { private fun mapLastMessageText(message: Message?): String? = message?.run {
return if (message == null) { if (this.message.isEmpty() && attachments?.isNotEmpty() == true) {
null message.attachments?.let { mapAttachmentText(it[0]) }
} else { } else {
return if (message.message.isEmpty() && message.attachments?.isNotEmpty() == true) { this.message
mapAttachmentText(message.attachments!![0])
} else {
message.message
}
} }
} }
private fun mapAttachmentText(attachment: Attachment): String = private fun mapAttachmentText(attachment: Attachment): String = context.getString(R.string.msg_sent_attachment)
context.getString(R.string.msg_sent_attachment)
private suspend fun updateSubscription(data: Subscription): ChatRoomEntity? { private suspend fun updateSubscription(data: Subscription): ChatRoomEntity? {
return retryDB("getRoom(${data.roomId}") { chatRoomDao().getSync(data.roomId) }?.let { current -> return retryDB("getRoom(${data.roomId}") { chatRoomDao().getSync(data.roomId) }?.let { current ->
...@@ -431,12 +409,10 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -431,12 +409,10 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
} }
} }
private suspend fun insertChatRoom(data: BaseRoom): ChatRoomEntity? { private suspend fun insertChatRoom(data: BaseRoom): ChatRoomEntity? = when (data) {
return when (data) { is Room -> insertRoom(data)
is Room -> insertRoom(data) is Subscription -> insertSubscription(data)
is Subscription -> insertSubscription(data) else -> null
else -> null
}
} }
private suspend fun insertRoom(data: Room): ChatRoomEntity? { private suspend fun insertRoom(data: Room): ChatRoomEntity? {
......
...@@ -115,12 +115,12 @@ fun Attachment.asEntity(msgId: String, context: Context): List<BaseMessageEntity ...@@ -115,12 +115,12 @@ fun Attachment.asEntity(msgId: String, context: Context): List<BaseMessageEntity
val text = mapAttachmentText(text, attachments?.firstOrNull(), context) val text = mapAttachmentText(text, attachments?.firstOrNull(), context)
val entity = AttachmentEntity( list.add(AttachmentEntity(
_id = attachmentId, _id = attachmentId,
messageId = msgId, messageId = msgId,
title = title, title = title,
type = type, type = type,
description = description, description = description,
text = text, text = text,
titleLink = titleLink, titleLink = titleLink,
titleLinkDownload = titleLinkDownload.orFalse(), titleLinkDownload = titleLinkDownload.orFalse(),
...@@ -144,16 +144,14 @@ fun Attachment.asEntity(msgId: String, context: Context): List<BaseMessageEntity ...@@ -144,16 +144,14 @@ fun Attachment.asEntity(msgId: String, context: Context): List<BaseMessageEntity
buttonAlignment = buttonAlignment, buttonAlignment = buttonAlignment,
hasActions = actions?.isNotEmpty() == true, hasActions = actions?.isNotEmpty() == true,
hasFields = fields?.isNotEmpty() == true hasFields = fields?.isNotEmpty() == true
) ))
list.add(entity)
fields?.forEach { field -> fields?.forEach { field ->
val entity = AttachmentFieldEntity( list.add(AttachmentFieldEntity(
attachmentId = attachmentId, attachmentId = attachmentId,
title = field.title, title = field.title,
value = field.value value = field.value
) ))
list.add(entity)
} }
actions?.forEach { action -> actions?.forEach { action ->
...@@ -175,18 +173,14 @@ fun Attachment.asEntity(msgId: String, context: Context): List<BaseMessageEntity ...@@ -175,18 +173,14 @@ fun Attachment.asEntity(msgId: String, context: Context): List<BaseMessageEntity
return list return list
} }
fun mapAttachmentText(text: String?, attachment: Attachment?, context: Context): String? { fun mapAttachmentText(text: String?, attachment: Attachment?, context: Context): String? = attachment?.run {
return if (attachment != null) { when {
when { imageUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_photo)
attachment.imageUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_photo) videoUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_video)
attachment.videoUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_video) audioUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_audio)
attachment.audioUrl.isNotNullNorEmpty() -> context.getString(R.string.msg_preview_audio) titleLink.isNotNullNorEmpty() &&
attachment.titleLink.isNotNullNorEmpty() && type?.contentEquals("file") == true ->
attachment.type?.contentEquals("file") == true -> context.getString(R.string.msg_preview_file)
context.getString(R.string.msg_preview_file) else -> text
else -> text
}
} else {
text
} }
} } ?: text
\ No newline at end of file
...@@ -36,8 +36,7 @@ class FavoriteMessagesPresenter @Inject constructor( ...@@ -36,8 +36,7 @@ class FavoriteMessagesPresenter @Inject constructor(
try { try {
view.showLoading() view.showLoading()
dbManager.getRoom(roomId)?.let { dbManager.getRoom(roomId)?.let {
val favoriteMessages = val favoriteMessages = client.getFavoriteMessages(roomId, roomTypeOf(it.chatRoom.type), offset)
client.getFavoriteMessages(roomId, roomTypeOf(it.chatRoom.type), offset)
val messageList = mapper.map(favoriteMessages.result, asNotReversed = true) val messageList = mapper.map(favoriteMessages.result, asNotReversed = true)
view.showFavoriteMessages(messageList) view.showFavoriteMessages(messageList)
offset += 1 * 30 offset += 1 * 30
......
...@@ -25,11 +25,9 @@ import dagger.android.support.AndroidSupportInjection ...@@ -25,11 +25,9 @@ import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_favorite_messages.* import kotlinx.android.synthetic.main.fragment_favorite_messages.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(chatRoomId: String): Fragment { fun newInstance(chatRoomId: String): Fragment = FavoriteMessagesFragment().apply {
return FavoriteMessagesFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(INTENT_CHAT_ROOM_ID, chatRoomId)
putString(INTENT_CHAT_ROOM_ID, chatRoomId)
}
} }
} }
...@@ -48,12 +46,9 @@ class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView { ...@@ -48,12 +46,9 @@ class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { chatRoomId = getString(INTENT_CHAT_ROOM_ID, "")
chatRoomId = bundle.getString(INTENT_CHAT_ROOM_ID) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
...@@ -30,11 +30,9 @@ import dagger.android.support.AndroidSupportInjection ...@@ -30,11 +30,9 @@ import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_files.* import kotlinx.android.synthetic.main.fragment_files.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(chatRoomId: String): Fragment { fun newInstance(chatRoomId: String): Fragment = FilesFragment().apply {
return FilesFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
}
} }
} }
...@@ -55,12 +53,9 @@ class FilesFragment : Fragment(), FilesView { ...@@ -55,12 +53,9 @@ class FilesFragment : Fragment(), FilesView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { chatRoomId = getString(BUNDLE_CHAT_ROOM_ID, "")
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
...@@ -11,8 +11,7 @@ object AndroidPermissionsHelper { ...@@ -11,8 +11,7 @@ object AndroidPermissionsHelper {
const val WRITE_EXTERNAL_STORAGE_CODE = 1 const val WRITE_EXTERNAL_STORAGE_CODE = 1
fun checkPermission(context: Context, permission: String): Boolean { fun checkPermission(context: Context, permission: String): Boolean {
return ContextCompat.checkSelfPermission(context, permission) == return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
PackageManager.PERMISSION_GRANTED
} }
fun requestPermission(context: Activity, permission: String, requestCode: Int) { fun requestPermission(context: Activity, permission: String, requestCode: Int) {
......
...@@ -53,8 +53,8 @@ object ImageHelper { ...@@ -53,8 +53,8 @@ object ImageHelper {
) )
val toolbar = Toolbar(context).also { val toolbar = Toolbar(context).also {
it.inflateMenu(R.menu.image_actions) it.inflateMenu(R.menu.image_actions)
it.setOnMenuItemClickListener { it.setOnMenuItemClickListener { view ->
return@setOnMenuItemClickListener when (it.itemId) { return@setOnMenuItemClickListener when (view.itemId) {
R.id.action_save_image -> saveImage(context) R.id.action_save_image -> saveImage(context)
else -> true else -> true
} }
...@@ -62,20 +62,24 @@ object ImageHelper { ...@@ -62,20 +62,24 @@ object ImageHelper {
val titleSize = context.resources val titleSize = context.resources
.getDimensionPixelSize(R.dimen.viewer_toolbar_title) .getDimensionPixelSize(R.dimen.viewer_toolbar_title)
val titleTextView = TextView(context).also { val titleTextView = TextView(context).also { tv ->
it.text = imageName with(tv) {
it.setTextColor(Color.WHITE) text = imageName
it.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize.toFloat()) setTextColor(Color.WHITE)
it.ellipsize = TextUtils.TruncateAt.END setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize.toFloat())
it.setSingleLine() ellipsize = TextUtils.TruncateAt.END
it.typeface = Typeface.DEFAULT_BOLD setSingleLine()
it.setPadding(pad) typeface = Typeface.DEFAULT_BOLD
setPadding(pad)
}
} }
val backArrowView = ImageView(context).also { val backArrowView = ImageView(context).also { imgView ->
it.setImageResource(R.drawable.ic_arrow_back_white_24dp) with(imgView) {
it.setOnClickListener { imageViewer?.onDismiss() } setImageResource(R.drawable.ic_arrow_back_white_24dp)
it.setPadding(0, pad, pad, pad) setOnClickListener { imageViewer?.onDismiss() }
setPadding(0, pad, pad, pad)
}
} }
val layoutParams = AppBarLayout.LayoutParams( val layoutParams = AppBarLayout.LayoutParams(
...@@ -88,14 +92,16 @@ object ImageHelper { ...@@ -88,14 +92,16 @@ object ImageHelper {
} }
val appBarLayout = AppBarLayout(context).also { val appBarLayout = AppBarLayout(context).also {
it.layoutParams = lparams with(it) {
it.setBackgroundColor(Color.BLACK) layoutParams = lparams
it.addView( setBackgroundColor(Color.BLACK)
toolbar, AppBarLayout.LayoutParams( addView(
AppBarLayout.LayoutParams.MATCH_PARENT, toolbar, AppBarLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT AppBarLayout.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
) )
) )
}
} }
val builder = ImageViewer.createPipelineDraweeControllerBuilder() val builder = ImageViewer.createPipelineDraweeControllerBuilder()
......
...@@ -10,8 +10,9 @@ import chat.rocket.android.util.extensions.inflate ...@@ -10,8 +10,9 @@ import chat.rocket.android.util.extensions.inflate
import kotlinx.android.synthetic.main.avatar.view.* import kotlinx.android.synthetic.main.avatar.view.*
import kotlinx.android.synthetic.main.item_member.view.* import kotlinx.android.synthetic.main.item_member.view.*
class MembersAdapter(private val listener: (MemberUiModel) -> Unit) : class MembersAdapter(
RecyclerView.Adapter<MembersAdapter.ViewHolder>() { private val listener: (MemberUiModel) -> Unit
) : 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): MembersAdapter.ViewHolder =
...@@ -43,7 +44,8 @@ class MembersAdapter(private val listener: (MemberUiModel) -> Unit) : ...@@ -43,7 +44,8 @@ class MembersAdapter(private val listener: (MemberUiModel) -> Unit) :
fun bind(memberUiModel: MemberUiModel, listener: (MemberUiModel) -> Unit) = with(itemView) { fun bind(memberUiModel: MemberUiModel, listener: (MemberUiModel) -> Unit) = with(itemView) {
image_avatar.setImageURI(memberUiModel.avatarUri) image_avatar.setImageURI(memberUiModel.avatarUri)
text_member.content = memberUiModel.displayName text_member.content = memberUiModel.displayName
text_member.setCompoundDrawablesRelativeWithIntrinsicBounds(DrawableHelper.getUserStatusDrawable(memberUiModel.status, context), null, null, null) text_member.setCompoundDrawablesRelativeWithIntrinsicBounds(
DrawableHelper.getUserStatusDrawable(memberUiModel.status, context), null, null, null)
setOnClickListener { listener(memberUiModel) } setOnClickListener { listener(memberUiModel) }
} }
} }
......
...@@ -27,11 +27,9 @@ import kotlinx.android.synthetic.main.app_bar_chat_room.* ...@@ -27,11 +27,9 @@ import kotlinx.android.synthetic.main.app_bar_chat_room.*
import kotlinx.android.synthetic.main.fragment_members.* import kotlinx.android.synthetic.main.fragment_members.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(chatRoomId: String): Fragment { fun newInstance(chatRoomId: String): Fragment = MembersFragment().apply {
return MembersFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
}
} }
} }
...@@ -52,12 +50,9 @@ class MembersFragment : Fragment(), MembersView { ...@@ -52,12 +50,9 @@ class MembersFragment : Fragment(), MembersView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { chatRoomId = getString(BUNDLE_CHAT_ROOM_ID, "")
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
...@@ -80,7 +75,7 @@ class MembersFragment : Fragment(), MembersView { ...@@ -80,7 +75,7 @@ class MembersFragment : Fragment(), MembersView {
setupToolbar(total) setupToolbar(total)
if (adapter.itemCount == 0) { if (adapter.itemCount == 0) {
adapter.prependData(dataSet) adapter.prependData(dataSet)
if (dataSet.size >= 59) { // TODO Check why the API retorns the specified count -1 if (dataSet.size >= 59) { // TODO Check why the API returns the specified count -1
recycler_view.addOnScrollListener(object : recycler_view.addOnScrollListener(object :
EndlessRecyclerViewScrollListener(linearLayoutManager) { EndlessRecyclerViewScrollListener(linearLayoutManager) {
override fun onLoadMore( override fun onLoadMore(
......
...@@ -25,11 +25,9 @@ import dagger.android.support.AndroidSupportInjection ...@@ -25,11 +25,9 @@ import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_mentions.* import kotlinx.android.synthetic.main.fragment_mentions.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(chatRoomId: String): Fragment { fun newInstance(chatRoomId: String): Fragment = MentionsFragment().apply {
return MentionsFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
}
} }
} }
...@@ -48,12 +46,9 @@ class MentionsFragment : Fragment(), MentionsView { ...@@ -48,12 +46,9 @@ class MentionsFragment : Fragment(), MentionsView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { chatRoomId = getString(BUNDLE_CHAT_ROOM_ID, "")
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
...@@ -25,11 +25,9 @@ import dagger.android.support.AndroidSupportInjection ...@@ -25,11 +25,9 @@ import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_pinned_messages.* import kotlinx.android.synthetic.main.fragment_pinned_messages.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(chatRoomId: String): Fragment { fun newInstance(chatRoomId: String): Fragment = PinnedMessagesFragment().apply {
return PinnedMessagesFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
}
} }
} }
...@@ -48,12 +46,9 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView { ...@@ -48,12 +46,9 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { chatRoomId = getString(BUNDLE_CHAT_ROOM_ID, "")
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
...@@ -38,13 +38,17 @@ class PreferencesFragment : Fragment(), PreferencesView { ...@@ -38,13 +38,17 @@ class PreferencesFragment : Fragment(), PreferencesView {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupListeners() setupListeners()
presenter.loadAnalyticsTrackingInformation() presenter.loadAnalyticsTrackingInformation()
analyticsManager.logScreenView(ScreenViewEvent.Preferences) analyticsManager.logScreenView(ScreenViewEvent.Preferences)
} }
override fun onResume() {
setupToolbar()
super.onResume()
}
override fun setupAnalyticsTrackingView(isAnalyticsTrackingEnabled: Boolean) { override fun setupAnalyticsTrackingView(isAnalyticsTrackingEnabled: Boolean) {
if (BuildConfig.FLAVOR == "foss") { if (BuildConfig.FLAVOR == "foss") {
switch_analytics_tracking.isChecked = false switch_analytics_tracking.isChecked = false
......
...@@ -115,7 +115,7 @@ class ProfilePresenter @Inject constructor( ...@@ -115,7 +115,7 @@ class ProfilePresenter @Inject constructor(
uriInteractor.getInputStream(uri) uriInteractor.getInputStream(uri)
} }
} }
user?.username?.let { view.reloadUserAvatar(it) } user?.username?.let { view.reloadUserAvatar(serverUrl.avatarUrl(it)) }
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
view.showMessage(it) view.showMessage(it)
...@@ -143,7 +143,7 @@ class ProfilePresenter @Inject constructor( ...@@ -143,7 +143,7 @@ class ProfilePresenter @Inject constructor(
} }
} }
user?.username?.let { view.reloadUserAvatar(it) } user?.username?.let { view.reloadUserAvatar(serverUrl.avatarUrl(it)) }
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
view.showMessage(it) view.showMessage(it)
...@@ -163,7 +163,7 @@ class ProfilePresenter @Inject constructor( ...@@ -163,7 +163,7 @@ class ProfilePresenter @Inject constructor(
user?.id?.let { id -> user?.id?.let { id ->
retryIO { client.resetAvatar(id) } retryIO { client.resetAvatar(id) }
} }
user?.username?.let { view.reloadUserAvatar(it) } user?.username?.let { view.reloadUserAvatar(serverUrl.avatarUrl(it)) }
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
view.showMessage(it) view.showMessage(it)
......
...@@ -94,11 +94,13 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -94,11 +94,13 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (resultData != null && resultCode == Activity.RESULT_OK) { resultData?.run {
if (requestCode == REQUEST_CODE_FOR_PERFORM_SAF) { if (resultCode == Activity.RESULT_OK) {
presenter.updateAvatar(resultData.data) if (requestCode == REQUEST_CODE_FOR_PERFORM_SAF) {
} else if (requestCode == REQUEST_CODE_FOR_PERFORM_CAMERA) { data?.let { presenter.updateAvatar(it) }
presenter.preparePhotoAndUpdateAvatar(resultData.extras["data"] as Bitmap) } else if (requestCode == REQUEST_CODE_FOR_PERFORM_CAMERA) {
extras?.get("data")?.let { presenter.preparePhotoAndUpdateAvatar(it as Bitmap) }
}
} }
} }
} }
...@@ -203,8 +205,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -203,8 +205,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
} }
private fun setupToolbar() { private fun setupToolbar() {
(activity as AppCompatActivity?)?.supportActionBar?.title = (activity as AppCompatActivity?)?.supportActionBar?.title = getString(R.string.title_profile)
getString(R.string.title_profile)
} }
private fun setupListeners() { private fun setupListeners() {
...@@ -293,19 +294,14 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -293,19 +294,14 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
} }
fun showDeleteAccountDialog() { fun showDeleteAccountDialog() {
val passwordEditText = EditText(context)
passwordEditText.hint = getString(R.string.msg_password)
context?.let { context?.let {
val builder = AlertDialog.Builder(it) val passwordEText = EditText(context);
builder.setTitle(R.string.title_are_you_sure) val mDialogView = LayoutInflater.from(it).inflate(R.layout.item_account_delete, null)
.setView(passwordEditText) val mBuilder = AlertDialog.Builder(it)
.setPositiveButton(R.string.action_delete_account) { _, _ ->
presenter.deleteAccount(passwordEditText.text.toString()) mBuilder.setView(mDialogView).setPositiveButton(R.string.action_delete_account) { _, _ ->
} presenter.deleteAccount(passwordEText.text.toString())
.setNegativeButton(android.R.string.no) { dialog, _ -> dialog.cancel() } }.setNegativeButton(android.R.string.no) { dialog, _ -> dialog.cancel() }.create().show()
.create()
.show()
} }
} }
} }
...@@ -12,13 +12,14 @@ import android.os.Build ...@@ -12,13 +12,14 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import android.text.Html
import android.text.Spanned
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.app.RemoteInput import androidx.core.app.RemoteInput
import android.text.Html
import android.text.Spanned
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.main.ui.MainActivity import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.server.domain.GetAccountInteractor import chat.rocket.android.server.domain.GetAccountInteractor
...@@ -303,7 +304,11 @@ class PushManager @Inject constructor( ...@@ -303,7 +304,11 @@ class PushManager @Inject constructor(
// CharSequence extensions // CharSequence extensions
private fun CharSequence.fromHtml(): Spanned { private fun CharSequence.fromHtml(): Spanned {
return Html.fromHtml(this as String) return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(this as String, FROM_HTML_MODE_LEGACY, null, null)
} else {
Html.fromHtml(this as String)
}
} }
// NotificationCompat.Builder extensions // NotificationCompat.Builder extensions
...@@ -383,12 +388,12 @@ data class PushMessage( ...@@ -383,12 +388,12 @@ data class PushMessage(
) : Parcelable { ) : Parcelable {
constructor(parcel: Parcel) : this( constructor(parcel: Parcel) : this(
parcel.readString().orEmpty(),
parcel.readString().orEmpty(),
parcel.readParcelable(PushMessage::class.java.classLoader) ?: PushInfo.EMPTY,
parcel.readString(), parcel.readString(),
parcel.readString(), parcel.readString(),
parcel.readParcelable(PushMessage::class.java.classLoader), parcel.readString().orEmpty(),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString(), parcel.readString(),
parcel.readString()) parcel.readString())
...@@ -433,9 +438,9 @@ data class PushInfo @KotshiConstructor constructor( ...@@ -433,9 +438,9 @@ data class PushInfo @KotshiConstructor constructor(
} }
constructor(parcel: Parcel) : this( constructor(parcel: Parcel) : this(
parcel.readString(), parcel.readString().orEmpty(),
parcel.readString(), parcel.readString().orEmpty(),
roomTypeOf(parcel.readString()), roomTypeOf(parcel.readString().orEmpty()),
parcel.readString(), parcel.readString(),
parcel.readParcelable(PushInfo::class.java.classLoader)) parcel.readParcelable(PushInfo::class.java.classLoader))
...@@ -481,7 +486,7 @@ data class PushSender @KotshiConstructor constructor( ...@@ -481,7 +486,7 @@ data class PushSender @KotshiConstructor constructor(
val name: String? val name: String?
) : Parcelable { ) : Parcelable {
constructor(parcel: Parcel) : this( constructor(parcel: Parcel) : this(
parcel.readString(), parcel.readString().orEmpty(),
parcel.readString(), parcel.readString(),
parcel.readString()) parcel.readString())
......
...@@ -97,8 +97,8 @@ class ConnectionManager( ...@@ -97,8 +97,8 @@ class ConnectionManager(
resubscribeRooms() resubscribeRooms()
temporaryStatus?.let { status -> temporaryStatus?.let { tempStatus ->
client.setTemporaryStatus(status) client.setTemporaryStatus(tempStatus)
} }
} }
is State.Waiting -> { is State.Waiting -> {
...@@ -135,9 +135,7 @@ class ConnectionManager( ...@@ -135,9 +135,7 @@ class ConnectionManager(
if (it.type == Type.Updated) { if (it.type == Type.Updated) {
if (it.data is Room) { if (it.data is Room) {
val room = it.data as Room val room = it.data as Room
roomsChannels[it.data.id]?.let { channel -> roomsChannels[it.data.id]?.offer(room)
channel.offer(room)
}
} }
} }
} }
...@@ -231,7 +229,7 @@ class ConnectionManager( ...@@ -231,7 +229,7 @@ class ConnectionManager(
} }
private fun resubscribeRooms() { private fun resubscribeRooms() {
roomMessagesChannels.toList().map { (roomId, channel) -> roomMessagesChannels.toList().map { (roomId, _) ->
client.subscribeRoomMessages(roomId) { _, id -> client.subscribeRoomMessages(roomId) { _, id ->
Timber.d("Subscribed to $roomId: $id") Timber.d("Subscribed to $roomId: $id")
subscriptionIdMap[roomId] = id subscriptionIdMap[roomId] = id
......
...@@ -14,7 +14,6 @@ import chat.rocket.core.model.Message ...@@ -14,7 +14,6 @@ import chat.rocket.core.model.Message
import chat.rocket.core.model.Reactions import chat.rocket.core.model.Reactions
import chat.rocket.core.model.attachment.Attachment import chat.rocket.core.model.attachment.Attachment
import chat.rocket.core.model.attachment.Color import chat.rocket.core.model.attachment.Color
import chat.rocket.core.model.attachment.DEFAULT_COLOR_STR
import chat.rocket.core.model.attachment.Field import chat.rocket.core.model.attachment.Field
import chat.rocket.core.model.attachment.actions.Action import chat.rocket.core.model.attachment.actions.Action
import chat.rocket.core.model.attachment.actions.ButtonAction import chat.rocket.core.model.attachment.actions.ButtonAction
...@@ -153,7 +152,7 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) { ...@@ -153,7 +152,7 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
null null
} }
val attachment = Attachment( list.add(Attachment(
title = title, title = title,
type = type, type = type,
description = description, description = description,
...@@ -179,10 +178,10 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) { ...@@ -179,10 +178,10 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
authorLink = authorLink, authorLink = authorLink,
fields = fields, fields = fields,
fallback = fallback, fallback = fallback,
buttonAlignment = if (actions != null && actions.isNotEmpty()) buttonAlignment ?: "vertical" else null, buttonAlignment = if (actions != null && actions.isNotEmpty()) buttonAlignment
?: "vertical" else null,
actions = actions actions = actions
) ))
list.add(attachment)
} }
} }
return list return list
......
...@@ -46,8 +46,8 @@ class DatabaseMessagesRepository( ...@@ -46,8 +46,8 @@ class DatabaseMessagesRepository(
dbManager.processMessagesBatch(listOf(message)).join() dbManager.processMessagesBatch(listOf(message)).join()
} }
override suspend fun saveAll(messages: List<Message>) { override suspend fun saveAll(newMessages: List<Message>) {
dbManager.processMessagesBatch(messages).join() dbManager.processMessagesBatch(newMessages).join()
} }
override suspend fun removeById(id: String) { override suspend fun removeById(id: String) {
...@@ -78,7 +78,7 @@ class DatabaseMessagesRepository( ...@@ -78,7 +78,7 @@ class DatabaseMessagesRepository(
override suspend fun getLastSyncDate(roomId: String): Long? = withContext(CommonPool) { override suspend fun getLastSyncDate(roomId: String): Long? = withContext(CommonPool) {
retryDB("getLastSync($roomId)") { retryDB("getLastSync($roomId)") {
dbManager.messageDao().getLastSync(roomId)?.let { it.timestamp } dbManager.messageDao().getLastSync(roomId)?.timestamp
} }
} }
} }
\ No newline at end of file
...@@ -14,13 +14,8 @@ class SharedPreferencesAccountsRepository( ...@@ -14,13 +14,8 @@ class SharedPreferencesAccountsRepository(
private val moshi: Moshi private val moshi: Moshi
) : AccountsRepository { ) : AccountsRepository {
override fun save(newAccount: Account) { override fun save(account: Account) {
val accounts = load() save(load().filter { item -> item.serverUrl != item.serverUrl }.toMutableList().apply { add(0, account) })
val newList = accounts.filter { account -> newAccount.serverUrl != account.serverUrl }
.toMutableList()
newList.add(0, newAccount)
save(newList)
} }
override fun load(): List<Account> { override fun load(): List<Account> {
...@@ -28,15 +23,11 @@ class SharedPreferencesAccountsRepository( ...@@ -28,15 +23,11 @@ class SharedPreferencesAccountsRepository(
val type = Types.newParameterizedType(List::class.java, Account::class.java) val type = Types.newParameterizedType(List::class.java, Account::class.java)
val adapter = moshi.adapter<List<Account>>(type) val adapter = moshi.adapter<List<Account>>(type)
return adapter.fromJson(json) ?: emptyList() return json?.let { adapter.fromJson(it) ?: emptyList() } ?: emptyList()
} }
override fun remove(serverUrl: String) { override fun remove(serverUrl: String) {
val accounts = load() save(load().filter { account -> serverUrl != account.serverUrl }.toMutableList())
val newList = accounts.filter { account -> serverUrl != account.serverUrl }
.toMutableList()
save(newList)
} }
private fun save(accounts: List<Account>) { private fun save(accounts: List<Account>) {
......
...@@ -15,8 +15,7 @@ class SharedPrefsBasicAuthRepository( ...@@ -15,8 +15,7 @@ class SharedPrefsBasicAuthRepository(
) : BasicAuthRepository { ) : BasicAuthRepository {
override fun save(basicAuth: BasicAuth) { override fun save(basicAuth: BasicAuth) {
val newList = load().filter { basicAuth -> basicAuth.host != basicAuth.host } val newList = load().filter { auth -> auth.host != auth.host }.toMutableList()
.toMutableList()
newList.add(0, basicAuth) newList.add(0, basicAuth)
save(newList) save(newList)
} }
...@@ -26,7 +25,7 @@ class SharedPrefsBasicAuthRepository( ...@@ -26,7 +25,7 @@ class SharedPrefsBasicAuthRepository(
val type = Types.newParameterizedType(List::class.java, BasicAuth::class.java) val type = Types.newParameterizedType(List::class.java, BasicAuth::class.java)
val adapter = moshi.adapter<List<BasicAuth>>(type) val adapter = moshi.adapter<List<BasicAuth>>(type)
return adapter.fromJson(json) ?: emptyList() return json?.let { adapter.fromJson(it) ?: emptyList() } ?: emptyList()
} }
private fun save(basicAuths: List<BasicAuth>) { private fun save(basicAuths: List<BasicAuth>) {
......
...@@ -106,18 +106,16 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback { ...@@ -106,18 +106,16 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
private fun finishActionMode() = actionMode?.finish() private fun finishActionMode() = actionMode?.finish()
private fun listenToChanges(): Disposable { private fun listenToChanges(): Disposable = Observables.combineLatest(
return Observables.combineLatest( text_new_password.asObservable(),
text_new_password.asObservable(), text_confirm_password.asObservable()
text_confirm_password.asObservable() ).subscribe {
).subscribe { val newPassword = it.first.toString()
val newPassword = it.first.toString() val newPasswordConfirmation = it.second.toString()
val newPasswordConfirmation = it.second.toString() if (newPassword.length > 5 && newPassword == newPasswordConfirmation) {
if (newPassword.length > 5 && newPassword == newPasswordConfirmation) { startActionMode()
startActionMode() } else {
} else { finishActionMode()
finishActionMode()
}
} }
} }
......
...@@ -2,6 +2,7 @@ package chat.rocket.android.settings.ui ...@@ -2,6 +2,7 @@ package chat.rocket.android.settings.ui
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Intent import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
...@@ -114,8 +115,7 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen ...@@ -114,8 +115,7 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen
} }
private fun setupToolbar() { private fun setupToolbar() {
(activity as AppCompatActivity?)?.supportActionBar?.title = (activity as AppCompatActivity?)?.supportActionBar?.title = getString(R.string.title_settings)
getString(R.string.title_settings)
} }
private fun shareApp() { private fun shareApp() {
...@@ -128,11 +128,12 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen ...@@ -128,11 +128,12 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen
} }
private fun contactSupport() { private fun contactSupport() {
with(Intent(Intent.ACTION_SEND)) { val uriText = "mailto:${"support@rocket.chat"}" +
type = "message/rfc822" "?subject=" + Uri.encode(getString(R.string.msg_android_app_support)) +
putExtra(Intent.EXTRA_EMAIL, arrayOf("support@rocket.chat")) "&body=" + Uri.encode(getDeviceAndAppInformation())
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.msg_android_app_support))
putExtra(Intent.EXTRA_TEXT, getDeviceAndAppInformation()) with(Intent(Intent.ACTION_SENDTO)) {
data = uriText.toUri()
try { try {
startActivity(Intent.createChooser(this, getString(R.string.msg_send_email))) startActivity(Intent.createChooser(this, getString(R.string.msg_send_email)))
} catch (ex: ActivityNotFoundException) { } catch (ex: ActivityNotFoundException) {
......
...@@ -40,7 +40,7 @@ class UserDetailsPresenter @Inject constructor( ...@@ -40,7 +40,7 @@ class UserDetailsPresenter @Inject constructor(
dbManager.getUser(userId)?.let { dbManager.getUser(userId)?.let {
userEntity = it userEntity = it
val avatarUrl = val avatarUrl =
userEntity.username?.let { currentServer.avatarUrl(avatar = it) } userEntity.username?.let { username -> currentServer.avatarUrl(avatar = username) }
val username = userEntity.username val username = userEntity.username
val name = userEntity.name val name = userEntity.name
val utcOffset = val utcOffset =
......
...@@ -29,11 +29,9 @@ import kotlinx.android.synthetic.main.app_bar_chat_room.* ...@@ -29,11 +29,9 @@ import kotlinx.android.synthetic.main.app_bar_chat_room.*
import kotlinx.android.synthetic.main.fragment_user_details.* import kotlinx.android.synthetic.main.fragment_user_details.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(userId: String): Fragment { fun newInstance(userId: String): Fragment = UserDetailsFragment().apply {
return UserDetailsFragment().apply { arguments = Bundle(1).apply {
arguments = Bundle(1).apply { putString(BUNDLE_USER_ID, userId)
putString(BUNDLE_USER_ID, userId)
}
} }
} }
...@@ -52,12 +50,9 @@ class UserDetailsFragment : Fragment(), UserDetailsView { ...@@ -52,12 +50,9 @@ class UserDetailsFragment : Fragment(), UserDetailsView {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
val bundle = arguments arguments?.run {
if (bundle != null) { userId = getString(BUNDLE_USER_ID, "")
userId = bundle.getString(BUNDLE_USER_ID) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
......
...@@ -191,7 +191,7 @@ class HttpLoggingInterceptor constructor(private val logger: Logger) : Intercept ...@@ -191,7 +191,7 @@ class HttpLoggingInterceptor constructor(private val logger: Logger) : Intercept
val responseBody = response.body() val responseBody = response.body()
val contentLength = responseBody!!.contentLength() val contentLength = responseBody!!.contentLength()
val bodySize = if (contentLength != -1L) contentLength.toString() + "-byte" else "unknown-length" val bodySize = if (contentLength != -1L) "$contentLength-byte" else "unknown-length"
val responseStr = if (response.message().isEmpty()) "" else " ${response.message()}" val responseStr = if (response.message().isEmpty()) "" else " ${response.message()}"
logger.log("<-- ${response.code()}$responseStr ${response.request().url()}" logger.log("<-- ${response.code()}$responseStr ${response.request().url()}"
+ " (" + tookMs + "ms" + (if (!logHeaders) ", $bodySize body" else "") + ')'.toString()) + " (" + tookMs + "ms" + (if (!logHeaders) ", $bodySize body" else "") + ')'.toString())
......
...@@ -69,11 +69,8 @@ fun String.userId(userId: String?): String? { ...@@ -69,11 +69,8 @@ fun String.userId(userId: String?): String? {
return userId?.let { this.replace(it, "") } return userId?.let { this.replace(it, "") }
} }
fun String.lowercaseUrl(): String? { fun String.lowercaseUrl(): String? = HttpUrl.parse(this)?.run {
val httpUrl = HttpUrl.parse(this) newBuilder().scheme(scheme().toLowerCase()).build().toString()
val newScheme = httpUrl?.scheme()?.toLowerCase()
return httpUrl?.newBuilder()?.scheme(newScheme)?.build()?.toString()
} }
fun String?.isNotNullNorEmpty(): Boolean = this != null && this.isNotEmpty() fun String?.isNotNullNorEmpty(): Boolean = this != null && this.isNotEmpty()
......
...@@ -80,12 +80,10 @@ fun AppCompatActivity.toPreviousView() { ...@@ -80,12 +80,10 @@ fun AppCompatActivity.toPreviousView() {
} }
fun Activity.hideKeyboard() { fun Activity.hideKeyboard() {
if (currentFocus != null) { currentFocus?.run {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).also {
imm.hideSoftInputFromWindow( it.hideSoftInputFromWindow(windowToken, InputMethodManager.RESULT_UNCHANGED_SHOWN)
currentFocus.windowToken, }
InputMethodManager.RESULT_UNCHANGED_SHOWN
)
} }
} }
......
...@@ -51,7 +51,7 @@ fun Uri.getFileSize(context: Context): Int { ...@@ -51,7 +51,7 @@ fun Uri.getFileSize(context: Context): Int {
fun Uri.getMimeType(context: Context): String { fun Uri.getMimeType(context: Context): String {
return if (scheme == ContentResolver.SCHEME_CONTENT) { return if (scheme == ContentResolver.SCHEME_CONTENT) {
context.contentResolver.getType(this) context.contentResolver?.getType(this) ?: ""
} else { } else {
val fileExtension = MimeTypeMap.getFileExtensionFromUrl(toString()) val fileExtension = MimeTypeMap.getFileExtensionFromUrl(toString())
if (fileExtension != null) { if (fileExtension != null) {
......
...@@ -27,13 +27,10 @@ class AdminPanelWebViewFragment : DaggerFragment() { ...@@ -27,13 +27,10 @@ class AdminPanelWebViewFragment : DaggerFragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val bundle = arguments arguments?.run {
if (bundle != null) { webPageUrl = getString(BUNDLE_WEB_PAGE_URL, "")
webPageUrl = bundle.getString(BUNDLE_WEB_PAGE_URL) userToken = getString(BUNDLE_USER_TOKEN, "")
userToken = bundle.getString(BUNDLE_USER_TOKEN) } ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
} }
override fun onCreateView( override fun onCreateView(
...@@ -65,7 +62,7 @@ class AdminPanelWebViewFragment : DaggerFragment() { ...@@ -65,7 +62,7 @@ class AdminPanelWebViewFragment : DaggerFragment() {
web_view.webViewClient = object : WebViewClient() { web_view.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) { override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url) super.onPageFinished(view, url)
ui { _ -> ui {
view_loading.hide() view_loading.hide()
web_view.evaluateJavascript("Meteor.loginWithToken('$userToken', function() { })") {} web_view.evaluateJavascript("Meteor.loginWithToken('$userToken', function() { })") {}
} }
......
...@@ -15,7 +15,7 @@ import chat.rocket.android.chatrooms.adapter.RoomsAdapter ...@@ -15,7 +15,7 @@ import chat.rocket.android.chatrooms.adapter.RoomsAdapter
* @see RecyclerView.ItemDecoration * @see RecyclerView.ItemDecoration
*/ */
class DividerItemDecoration() : RecyclerView.ItemDecoration() { class DividerItemDecoration() : RecyclerView.ItemDecoration() {
private lateinit var divider: Drawable private var divider: Drawable? = null
private var boundStart = 0 private var boundStart = 0
private var boundEnd = 0 private var boundEnd = 0
...@@ -40,10 +40,7 @@ class DividerItemDecoration() : RecyclerView.ItemDecoration() { ...@@ -40,10 +40,7 @@ class DividerItemDecoration() : RecyclerView.ItemDecoration() {
// Custom divider will be used. // Custom divider will be used.
constructor(context: Context, @DrawableRes drawableResId: Int) : this() { constructor(context: Context, @DrawableRes drawableResId: Int) : this() {
val customDrawable = ContextCompat.getDrawable(context, drawableResId) divider = ContextCompat.getDrawable(context, drawableResId)
if (customDrawable != null) {
divider = customDrawable
}
} }
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
...@@ -62,8 +59,8 @@ class DividerItemDecoration() : RecyclerView.ItemDecoration() { ...@@ -62,8 +59,8 @@ class DividerItemDecoration() : RecyclerView.ItemDecoration() {
val bottom = child.bottom + params.bottomMargin val bottom = child.bottom + params.bottomMargin
val top = bottom - divider.intrinsicHeight val top = bottom - divider.intrinsicHeight
divider.setBounds(left, top, right, bottom) divider?.setBounds(left, top, right, bottom)
divider.draw(c) divider?.draw(c)
} }
} }
......
<vector android:height="24dp" android:viewportHeight="100"
android:viewportWidth="100" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ededed" android:pathData="M50,100q-24.66,0 -49.32,0c-0.57,0 -0.68,-0.11 -0.68,-0.68Q0,50 0,0.68C0,0.11 0.11,0 0.68,0Q50,0 99.32,0c0.57,0 0.68,0.11 0.68,0.68q0,49.32 0,98.64c0,0.57 -0.11,0.68 -0.68,0.68Q74.66,100 50,100Z"/>
<path android:fillColor="#afafae" android:pathData="M49.42,90C41.72,90 34,90 26.34,90a13.82,13.82 0,0 1,-8.55 -2.75A11.18,11.18 0,0 1,13.22 79a46.76,46.76 0,0 1,3 -21.44,17.06 17.06,0 0,1 6.56,-8.48 15.67,15.67 0,0 1,7.3 -2.28,4.52 4.52,0 0,1 2.84,1c1.62,1 3.18,2.14 4.86,3.05a23.24,23.24 0,0 0,20.34 1.5A25.39,25.39 0,0 0,65 48.51c2.81,-2.26 5.65,-1.76 8.61,-0.71 3.73,1.32 6.24,4 8.11,7.39A35.18,35.18 0,0 1,85.31 67,54.2 54.2,0 0,1 86,77.31a12.47,12.47 0,0 1,-4 9.28,12.65 12.65,0 0,1 -7.33,3.22c-3.9,0.4 -7.82,0.13 -11.73,0.17C58.41,90 53.92,90 49.42,90Z"/>
<path android:fillColor="#afafae" android:pathData="M69.35,30.28c0.4,10.36 -8.74,20 -19.89,19.93s-19.92,-9.58 -19.89,-20 8.81,-19.93 20,-19.88C60.64,10.35 69.77,19.87 69.35,30.28Z"/>
</vector>
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
android:layout_width="120dp" android:layout_width="120dp"
android:layout_height="120dp" android:layout_height="120dp"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:background="@drawable/bg_empty_user_avatar"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
......
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="chat.rocket.android.about.ui.AboutFragment"> tools:context="chat.rocket.android.about.ui.AboutFragment">
<ImageView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/image_app_name" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="60dp" android:paddingTop="50dp"
android:src="@drawable/ic_app_name" android:layout_gravity="center">
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<ImageView <ImageView
android:layout_width="160dp" android:id="@+id/image_app_name"
android:layout_height="160dp" android:layout_width="wrap_content"
android:src="@drawable/ic_launcher_foreground" android:layout_height="60dp"
app:layout_constraintStart_toStartOf="parent" android:src="@drawable/ic_app_name"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/image_app_name" app:layout_constraintBottom_toBottomOf="parent"
android:adjustViewBounds="true" app:layout_constraintStart_toStartOf="parent"
android:scaleX="1.5" app:layout_constraintEnd_toEndOf="parent" />
android:scaleY="1.5" />
<TextView <ImageView
android:id="@+id/text_version_name" android:layout_width="160dp"
android:layout_width="wrap_content" android:layout_height="160dp"
android:layout_height="wrap_content" android:adjustViewBounds="true"
tools:text="Version alpha2.0.1" android:scaleX="1.5"
app:layout_constraintStart_toStartOf="parent" android:scaleY="1.5"
app:layout_constraintEnd_toEndOf="parent" android:src="@drawable/ic_launcher_foreground"
app:layout_constraintTop_toBottomOf="@+id/image_app_name" app:layout_constraintBottom_toTopOf="@id/image_app_name"
android:layout_marginTop="16dp" app:layout_constraintEnd_toEndOf="parent"
android:textColor="@color/colorSecondaryText" app:layout_constraintStart_toStartOf="parent"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"/> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/text_build_number" android:id="@+id/text_version_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="Build # 2000" tools:text="Version alpha2.0.1"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_version_name" app:layout_constraintTop_toBottomOf="@+id/image_app_name"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
android:textColor="@color/colorSecondaryText" /> android:textColor="@color/colorSecondaryText"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"/>
<TextView
android:id="@+id/text_build_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Build # 2000"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_version_name"
android:layout_marginTop="8dp"
android:textColor="@color/colorSecondaryText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </ScrollView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/screen_edge_left_and_right_margins">
<TextView
android:id="@+id/text_reset_password"
style="@style/Authentication.TextView.Headline"
android:text="@string/title_are_you_sure"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/text_delete_account_password"
style="@style/Authentication.EditText.Border"
android:layout_marginTop="16dp"
android:drawableStart="@drawable/ic_key_black_20dp"
android:hint="@string/msg_password"
android:imeOptions="actionDone"
android:inputType="textPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_reset_password" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
android:id="@+id/day" android:id="@+id/day"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" android:layout_marginStart="16dp"
android:layout_marginRight="16dp" android:layout_marginEnd="16dp"
android:textAppearance="@style/Message.DayMarker" android:textAppearance="@style/Message.DayMarker"
tools:text="Wednesday" /> tools:text="Wednesday" />
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
layout="@layout/avatar" layout="@layout/avatar"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/message_header" /> app:layout_constraintTop_toTopOf="@+id/message_header" />
<LinearLayout <LinearLayout
...@@ -95,17 +95,16 @@ ...@@ -95,17 +95,16 @@
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:orientation="horizontal" android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@+id/layout_avatar"
app:layout_constraintStart_toEndOf="@+id/layout_avatar" app:layout_constraintStart_toEndOf="@+id/layout_avatar"
app:layout_constraintTop_toBottomOf="@+id/day_marker_layout"> app:layout_constraintTop_toBottomOf="@+id/day_marker_layout">
<TextView <TextView
android:id="@+id/text_sender" android:id="@+id/text_sender"
style="@style/Sender.Name.TextView" style="@style/Sender.Name.TextView"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_weight="1" android:maxLength="22"
tools:text="User Name with long name" /> tools:text="User Name with long name" />
<TextView <TextView
...@@ -123,7 +122,7 @@ ...@@ -123,7 +122,7 @@
android:layout_marginStart="4dp" android:layout_marginStart="4dp"
android:text="@string/msg_edited" android:text="@string/msg_edited"
android:textStyle="italic" android:textStyle="italic"
android:visibility="gone" android:visibility="invisible"
tools:visibility="visible" /> tools:visibility="visible" />
<ImageView <ImageView
...@@ -133,7 +132,7 @@ ...@@ -133,7 +132,7 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="4dp" android:layout_marginStart="4dp"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:visibility="gone" android:visibility="invisible"
app:srcCompat="@drawable/ic_action_message_star_24dp" app:srcCompat="@drawable/ic_action_message_star_24dp"
tools:visibility="visible" /> tools:visibility="visible" />
...@@ -141,7 +140,7 @@ ...@@ -141,7 +140,7 @@
android:id="@+id/read_receipt_view" android:id="@+id/read_receipt_view"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:visibility="gone" android:visibility="invisible"
app:srcCompat="@drawable/ic_check_unread_24dp" app:srcCompat="@drawable/ic_check_unread_24dp"
tools:visibility="visible" /> tools:visibility="visible" />
</LinearLayout> </LinearLayout>
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
android:id="@+id/image_avatar" android:id="@+id/image_avatar"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:background="@drawable/bg_empty_user_avatar"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
......
...@@ -324,6 +324,7 @@ ...@@ -324,6 +324,7 @@
<string name="chatroom_header">Kopf</string> <string name="chatroom_header">Kopf</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">Räume</string> <string name="header_channel">Räume</string>
<string name="header_private_groups">Private Räume</string> <string name="header_private_groups">Private Räume</string>
<string name="header_direct_messages">Direkt Nachrichten</string> <string name="header_direct_messages">Direkt Nachrichten</string>
......
...@@ -315,6 +315,7 @@ ...@@ -315,6 +315,7 @@
<string name="chatroom_header">Cabezazo</string> <string name="chatroom_header">Cabezazo</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">Canales</string> <string name="header_channel">Canales</string>
<string name="header_private_groups">Grupos privados</string> <string name="header_private_groups">Grupos privados</string>
<string name="header_direct_messages">Mensajes directos</string> <string name="header_direct_messages">Mensajes directos</string>
......
...@@ -318,6 +318,7 @@ ...@@ -318,6 +318,7 @@
<string name="chatroom_header">سرپیام</string> <string name="chatroom_header">سرپیام</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">کانال‌ها</string> <string name="header_channel">کانال‌ها</string>
<string name="header_private_groups">گروه‌های خصوصی</string> <string name="header_private_groups">گروه‌های خصوصی</string>
<string name="header_direct_messages">پیام‌های خصوصی</string> <string name="header_direct_messages">پیام‌های خصوصی</string>
......
...@@ -17,14 +17,14 @@ ...@@ -17,14 +17,14 @@
<string name="title_preferences">Préférences</string> <string name="title_preferences">Préférences</string>
<string name="title_change_password">Changer le mot de passe</string> <string name="title_change_password">Changer le mot de passe</string>
<string name="title_rate_us">évaluez nous</string> <string name="title_rate_us">évaluez nous</string>
<string name="title_admin_panel">Administration</string> <string name="title_admin_panel">l\' administration</string>
<string name="title_password">Changer le mot de passe</string> <string name="title_password">Changer le mot de passe</string>
<string name="title_update_profile">Mettre à jour le profil</string> <string name="title_update_profile">Mettre à jour le profil</string>
<string name="title_about">À propos</string> <string name="title_about">À propos</string>
<string name="title_create_channel">Créer salon</string> <string name="title_create_channel">Créer salon</string>
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">les permis</string>
<string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation --> <string name="title_are_you_sure">Êtes-vous sûr?</string>
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation --> <string name="title_channel_details">Détails de la chaîne</string>
<string name="title_topic">Sujet</string> <string name="title_topic">Sujet</string>
<string name="title_announcement">Annonce</string> <string name="title_announcement">Annonce</string>
<string name="title_description">La description</string> <string name="title_description">La description</string>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
<string name="action_create_channel">Créer salon</string> <string name="action_create_channel">Créer salon</string>
<string name="action_create">Créer</string> <string name="action_create">Créer</string>
<string name="action_logout">Se déconnecter</string> <string name="action_logout">Se déconnecter</string>
<string name="action_attach_a_files">Attach a file</string> <!-- TODO Add translation --> <string name="action_attach_a_files">Joindre un fichier</string>
<string name="action_confirm_password">Confirmer le mot de passe</string> <string name="action_confirm_password">Confirmer le mot de passe</string>
<string name="action_join_chat">Rejoignez le chat</string> <string name="action_join_chat">Rejoignez le chat</string>
<string name="action_add_account">Ajouter un compte</string> <string name="action_add_account">Ajouter un compte</string>
...@@ -53,23 +53,23 @@ ...@@ -53,23 +53,23 @@
<string name="action_select_photo_from_gallery">Sélectionner depuis la gallerie</string> <string name="action_select_photo_from_gallery">Sélectionner depuis la gallerie</string>
<string name="action_take_a_photo">Prendre une photo</string> <string name="action_take_a_photo">Prendre une photo</string>
<string name="action_reset_avatar">Réinitialiser l\'avatar</string> <string name="action_reset_avatar">Réinitialiser l\'avatar</string>
<string name="action_connect_server">Connect with a server</string> <!-- TODO Add translation --> <string name="action_connect_server">Se connecter avec un serveur</string>
<string name="action_join_community">Join in the community</string> <!-- TODO Add translation --> <string name="action_join_community">Rejoignez la communauté</string>
<string name="action_create_server">Create a new server</string> <!-- TODO Add translation --> <string name="action_create_server">Créer un nouveau serveur</string>
<string name="action_register">Register</string> <!-- TODO Add translation --> <string name="action_register">registre</string>
<string name="action_confirm">Confirm</string> <!-- TODO Add translation --> <string name="action_confirm">Confirmer</string>
<string name="action_delete_account">Delete account</string> <!-- TODO Add translation --> <string name="action_delete_account">Effacer le compte</string>
<!-- Settings List --> <!-- Settings List -->
<string-array name="settings_actions"> <string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation --> <item name="item_preferences">Préférences</item>
<item name="item_password">Change password</item> <!-- TODO Add translation --> <item name="item_password">Changer le mot de passe</item>
<item name="change_language">Change language</item> <!-- TODO Add translation --> <item name="change_language">Changer de langue</item>
<item name="item_share_app">Share app</item> <!-- TODO Add translation --> <item name="item_share_app">Partager l\'application</item>
<item name="item_rate_us">Rate us</item> <!-- TODO Add translation --> <item name="item_rate_us">Évaluez nous</item>
<item name="item_contact_us">Contact us</item> <!-- TODO Add translation --> <item name="item_contact_us">Contactez nous</item>
<item name="item_licence">Licence</item> <!-- TODO Add translation --> <item name="item_licence">les permis</item>
<item name="item_about">About</item> <!-- TODO Add translation --> <item name="item_about">Sur</item>
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
<string name="msg_content_description_log_in_using_gitlab">Connectez-vous en utilisant Gitlab</string> <string name="msg_content_description_log_in_using_gitlab">Connectez-vous en utilisant Gitlab</string>
<string name="msg_content_description_log_in_using_wordpress">Connectez-vous en utilisant WordPress</string> <string name="msg_content_description_log_in_using_wordpress">Connectez-vous en utilisant WordPress</string>
<string name="msg_content_description_send_message">Envoyer message</string> <string name="msg_content_description_send_message">Envoyer message</string>
<string name="msg_content_description_show_more_login_options">Show more login options</string> <!-- TODO Translate--> <string name="msg_content_description_show_more_login_options">montrer plus d\'options le login</string>
<string name="msg_content_description_show_attachment_options">Afficher les options de fichiers</string> <string name="msg_content_description_show_attachment_options">Afficher les options de fichiers</string>
<string name="msg_you">Vous</string> <string name="msg_you">Vous</string>
<string name="msg_unknown">Inconnu</string> <string name="msg_unknown">Inconnu</string>
...@@ -121,7 +121,7 @@ ...@@ -121,7 +121,7 @@
<string name="msg_preview_photo">Photo</string> <string name="msg_preview_photo">Photo</string>
<string name="msg_preview_file">Fichier</string> <string name="msg_preview_file">Fichier</string>
<string name="msg_no_messages_yet">Aucun message pour le moment</string> <string name="msg_no_messages_yet">Aucun message pour le moment</string>
<string name="msg_build">Build %1$d - %2$s - %3$s</string> <!-- TODO Add translation --> <string name="msg_build">bâtir %1$d - %2$s - %3$s</string>
<string name="msg_update_app_version_in_order_to_continue">La version du serveur est trop ancienne. Veuillez contacter l\'administateur pour mettre à jour le serveur afin de pouvoir vous y connecter.</string> <string name="msg_update_app_version_in_order_to_continue">La version du serveur est trop ancienne. Veuillez contacter l\'administateur pour mettre à jour le serveur afin de pouvoir vous y connecter.</string>
<string name="msg_ver_not_recommended"> <string name="msg_ver_not_recommended">
On dirait que la version de votre serveur est en dessous de la version recommandée %1$s.\nVous pouvez toujours vous connecter mais vous pouvez rencontrer des comportements inattendus.</string> On dirait que la version de votre serveur est en dessous de la version recommandée %1$s.\nVous pouvez toujours vous connecter mais vous pouvez rencontrer des comportements inattendus.</string>
...@@ -149,32 +149,32 @@ ...@@ -149,32 +149,32 @@
<string name="msg_send">envoyer</string> <string name="msg_send">envoyer</string>
<string name="msg_delete_message">Supprimer Message</string> <string name="msg_delete_message">Supprimer Message</string>
<string name="msg_delete_description">Êtes-vous sûr de vouloir supprimer ce message</string> <string name="msg_delete_description">Êtes-vous sûr de vouloir supprimer ce message</string>
<string name="msg_welcome_to_rocket_chat">Welcome to Rocket.Chat</string> <!-- TODO Add translation --> <string name="msg_welcome_to_rocket_chat">Bienvenue à Rocket.Chat</string>
<string name="msg_team_communication">Team Communication</string> <!-- TODO Translate --> <string name="msg_team_communication">Communication d\'équipe</string>
<string name="msg_login_with_email">Login with <b>e-mail</b></string> <!-- TODO Add translation --> <string name="msg_login_with_email">le login avec <b>e-mail</b></string>
<string name="msg_create_account">Create an account</string> <!-- TODO Add translation --> <string name="msg_create_account">Créer un compte</string>
<string name="msg_continue_with_facebook">Continue with <b>Facebook</b></string> <!-- TODO Add translation --> <string name="msg_continue_with_facebook">Continuer avec <b>Facebook</b></string>
<string name="msg_continue_with_github">Continue with <b>Github</b></string> <!-- TODO Add translation --> <string name="msg_continue_with_github">Continuer avec <b>Github</b></string>
<string name="msg_continue_with_google">Continue with <b>Google</b></string> <!-- TODO Add translation --> <string name="msg_continue_with_google">Continuer avec <b>Google</b></string>
<string name="msg_continue_with_linkedin">Continue with <b>Linkedin</b></string> <!-- TODO Add translation --> <string name="msg_continue_with_linkedin">Continuer avec <b>Linkedin</b></string>
<string name="msg_continue_with_gitlab">Continue with <b>GitLab</b></string> <!-- TODO Add translation --> <string name="msg_continue_with_gitlab">Continuer avec <b>GitLab</b></string>
<string name="msg_continue_with_wordpress">Continue with <b>WordPress</b></string> <!-- TODO Add translation --> <string name="msg_continue_with_wordpress">Continuer avec <b>WordPress</b></string>
<string name="msg_two_factor_authentication">Two-factor Authentication</string> <!-- TODO Add translation --> <string name="msg_two_factor_authentication">authentification à deux facteurs</string>
<string name="msg__your_2fa_code">What’s your 2FA code?</string> <!-- TODO Add translation --> <string name="msg__your_2fa_code">Quel est votre code 2FA?</string>
<string name="msg_view_more">view more</string> <!-- TODO - Add proper translation --> <string name="msg_view_more">voir de plus</string>
<string name="msg_view_less">view less</string> <!-- TODO - Add proper translation --> <string name="msg_view_less">voir de plus</string>
<string name="msg_permalink_copied">Permalink copied</string> <!-- TODO - Add proper translation --> <string name="msg_permalink_copied">Permalink copié</string>
<string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation --> <string name="msg_send_email">Envoyer email</string>
<string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation --> <string name="msg_android_app_support">Android app le support</string>
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation --> <string name="msg_muted_on_this_channel">Vous êtes en sourdine sur ce canal</string>
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation --> <string name="msg_no_topic">sujet non ajouté</string>
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation --> <string name="msg_no_announcement">annonce non ajoutée</string>
<string name="msg_no_description">No description added</string> <!-- TODO Add translation --> <string name="msg_no_description">description non ajoutée</string>
<string name="msg_unable_to_update_password">Unable to update password. Error message: %1$s</string> <!-- TODO - Add proper translation --> <string name="msg_unable_to_update_password">Impossible de mettre à jour le mot de passe. Message d\'erreur: %1$s</string>
<string name="msg_password_updated_successfully">Password updated successfully</string> <!-- TODO - Add proper translation --> <string name="msg_password_updated_successfully">Mot de passe mis à jour avec succès</string>
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="one">%1$s a réagi avec %2$s</item>
<item quantity="other">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="other">%1$s a réagi avec %2$s</item>
</plurals> </plurals>
<!-- Create channel messages --> <!-- Create channel messages -->
...@@ -225,10 +225,8 @@ ...@@ -225,10 +225,8 @@
<string name="action_msg_share">Partager</string> <string name="action_msg_share">Partager</string>
<string name="action_title_editing">Modification du message</string> <string name="action_title_editing">Modification du message</string>
<string name="action_msg_add_reaction">Ajouter une réaction</string> <string name="action_msg_add_reaction">Ajouter une réaction</string>
<!-- TODO - Add proper translation --> <string name="action_msg_copy_permalink">copie permalien</string>
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_report">rapport</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">L\'édition n\'est pas autorisée</string> <string name="permission_editing_not_allowed">L\'édition n\'est pas autorisée</string>
...@@ -319,6 +317,7 @@ ...@@ -319,6 +317,7 @@
<string name="chatroom_header">Entête</string> <string name="chatroom_header">Entête</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favoris</string>
<string name="header_channel">Salons</string> <string name="header_channel">Salons</string>
<string name="header_private_groups">Groupes privés</string> <string name="header_private_groups">Groupes privés</string>
<string name="header_direct_messages">Messages directs</string> <string name="header_direct_messages">Messages directs</string>
...@@ -334,14 +333,14 @@ ...@@ -334,14 +333,14 @@
<string name="message_information_title">Informations sur le message</string> <string name="message_information_title">Informations sur le message</string>
<string name="msg_log_out">Déconnecter…</string> <string name="msg_log_out">Déconnecter…</string>
<string name="msg_sent_attachment">Envoyé un fichier</string> <string name="msg_sent_attachment">Envoyé un fichier</string>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation--> <string name="message_room_changed_privacy">Changé de type de chambre : %1$s de %2$s</string>
<!-- User Details --> <!-- User Details -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation --> <string name="timezone">Fuseau horaire</string>
<!-- Report --> <!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation --> <string name="submit">Soumettre</string>
<string name="required">*required</string> <!-- TODO - Add proper translation --> <string name="required">*Obligatoire</string>
<string name="report_sent">Your report has been sent!</string> <!-- TODO - Add proper translation --> <string name="report_sent">Votre rapport a été envoyé!</string>
</resources> </resources>
...@@ -121,7 +121,7 @@ ...@@ -121,7 +121,7 @@
<string name="msg_preview_file">फ़ाइल</string> <string name="msg_preview_file">फ़ाइल</string>
<string name="msg_unread_messages">अपठित संदेश</string> <string name="msg_unread_messages">अपठित संदेश</string>
<string name="msg_no_messages_yet">अभी तक कोई पोस्ट नहीं</string> <string name="msg_no_messages_yet">अभी तक कोई पोस्ट नहीं</string>
<string name="msg_build">Build %1$d - %2$s - %3$s</string> <!-- TODO Add translation --> <string name="msg_build">निर्माण %1$d - %2$s - %3$s</string>
<string name="msg_update_app_version_in_order_to_continue">पुराना सर्वर वर्शन। जारी रखने के लिए सर्वर वर्शन को अद्यतन करने के लिए कृपया सर्वर व्यवस्थापक से संपर्क करें।</string> <string name="msg_update_app_version_in_order_to_continue">पुराना सर्वर वर्शन। जारी रखने के लिए सर्वर वर्शन को अद्यतन करने के लिए कृपया सर्वर व्यवस्थापक से संपर्क करें।</string>
<string name="msg_ver_not_recommended"> <string name="msg_ver_not_recommended">
ऐसा लगता है कि आपका सर्वर संस्करण अनुशंसित संस्करण %1$s के नीचे है।\nआप अभी भी लॉगिन कर सकते हैं लेकिन आप अप्रत्याशित व्यवहार का अनुभव कर सकते हैं ऐसा लगता है कि आपका सर्वर संस्करण अनुशंसित संस्करण %1$s के नीचे है।\nआप अभी भी लॉगिन कर सकते हैं लेकिन आप अप्रत्याशित व्यवहार का अनुभव कर सकते हैं
...@@ -319,6 +319,7 @@ ...@@ -319,6 +319,7 @@
<string name="chatroom_header">हैडर</string> <string name="chatroom_header">हैडर</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">पसंदीदा</string>
<string name="header_channel">चैनलों</string> <string name="header_channel">चैनलों</string>
<string name="header_private_groups">निजी समूहों</string> <string name="header_private_groups">निजी समूहों</string>
<string name="header_direct_messages">प्रत्यक्ष संदेश</string> <string name="header_direct_messages">प्रत्यक्ष संदेश</string>
......
...@@ -315,6 +315,7 @@ ...@@ -315,6 +315,7 @@
<string name="chatroom_header">Intestazione</string> <string name="chatroom_header">Intestazione</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">Canali</string> <string name="header_channel">Canali</string>
<string name="header_private_groups">Gruppi Privati</string> <string name="header_private_groups">Gruppi Privati</string>
<string name="header_direct_messages">Messaggi Diretti</string> <string name="header_direct_messages">Messaggi Diretti</string>
......
...@@ -319,6 +319,7 @@ ...@@ -319,6 +319,7 @@
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">チャンネル</string> <string name="header_channel">チャンネル</string>
<string name="header_private_groups">プライベートグループ</string> <string name="header_private_groups">プライベートグループ</string>
<string name="header_direct_messages">ダイレクトメッセージ</string> <string name="header_direct_messages">ダイレクトメッセージ</string>
......
...@@ -317,6 +317,7 @@ ...@@ -317,6 +317,7 @@
<string name="chatroom_header">Cabeçalho</string> <string name="chatroom_header">Cabeçalho</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favoritos</string>
<string name="header_channel">Canais</string> <string name="header_channel">Canais</string>
<string name="header_private_groups">Grupos Privados</string> <string name="header_private_groups">Grupos Privados</string>
<string name="header_direct_messages">Mensagens diretas</string> <string name="header_direct_messages">Mensagens diretas</string>
......
<resources>
<!-- Titles -->
<string name="title_sign_in_your_server">Entre no seu servidor</string>
<string name="title_log_in">Entrar</string>
<string name="title_share_the_app">Partilhe a Aplicação</string>
<string name="title_register_username">Registe um utilizador</string>
<string name="title_reset_password">Reponha a palavra-passe</string>
<string name="title_sign_up">Inscreva-se</string>
<string name="title_authentication">Autenticação</string>
<string name="title_legal_terms">Termos Legais</string>
<string name="title_chats">Conversas</string>
<string name="title_profile">Pefil</string>
<string name="title_members">Membros</string>
<string name="title_counted_members">Membros (%d)</string>
<string name="title_settings">Definições</string>
<string name="title_preferences">Preferências</string>
<string name="title_change_password">Alterar palavra-passe</string>
<string name="title_rate_us">Avalie-nos</string>
<string name="title_admin_panel">Painel de Administração</string>
<string name="title_password">Alterar palavra-passe</string>
<string name="title_update_profile">Actualizar perfil</string>
<string name="title_about">Acerca</string>
<string name="title_create_channel">Criar Canal</string>
<string name="title_licence">Licença</string>
<string name="title_are_you_sure">Tem a certeza?</string>
<string name="title_channel_details">Detalhes do Canal</string>
<string name="title_topic">Tópico</string>
<string name="title_announcement">Anúncio</string>
<string name="title_description">Descrição</string>
<!-- Actions -->
<string name="action_connect">Ligar</string>
<string name="action_use_this_username">Use este nome de utilizador</string>
<string name="action_terms_of_service">Termos do Serviço</string>
<string name="action_privacy_policy">Política de Privacidade</string>
<string name="action_search">Pesquisar</string>
<string name="action_update">Actualizar</string>
<string name="action_settings">Definições</string>
<string name="action_create_channel">Criar canal</string>
<string name="action_create">Criar</string>
<string name="action_logout">Terminar sessão</string>
<string name="action_attach_a_files">Enviar um ficheiro</string>
<string name="action_confirm_password">Confirme a alteração da palavra-passe</string>
<string name="action_join_chat">Entre no chat</string>
<string name="action_add_account">Adicionar conta</string>
<string name="action_online">Online</string>
<string name="action_away">Ausente</string>
<string name="action_busy">Ocupado</string>
<string name="action_invisible">Invisível</string>
<string name="action_drawing">A desenhar</string>
<string name="action_save_to_gallery">Guardar na galeria</string>
<string name="action_select_photo_from_gallery">Selecione a foto da galeria</string>
<string name="action_take_a_photo">Tire uma foto</string>
<string name="action_reset_avatar">Repor avatar</string>
<string name="action_connect_server">Ligue-se a um servidor</string>
<string name="action_join_community">Junte-se à comunidade</string>
<string name="action_create_server">Crie um novo servidor</string>
<string name="action_register">Registar</string>
<string name="action_confirm">Confirmar</string>
<string name="action_delete_account">Apagar conta</string>
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_preferences">Preferências</item>
<item name="item_password">Alterar palavra-passe</item>
<item name="change_language">Alterar idioma</item>
<item name="item_share_app">Partilhe a aplicação</item>
<item name="item_rate_us">Avalie-nos</item>
<item name="item_contact_us">Contacte-nos</item>
<item name="item_licence">Licença</item>
<item name="item_about">Acerca</item>
</string-array>
<!-- Regular information messages -->
<string name="msg_generic_error">Lamentamos, ocorreu um erro, tente novamente</string>
<string name="msg_no_data_to_display">Sem dados para mostrar</string>
<string name="msg_check_this_out">Experimente isto</string>
<string name="msg_share_using">Partilhe usando</string>
<string name="msg_profile_update_successfully">Perfil actualizado com sucesso</string>
<string name="msg_username">utilizador</string>
<string name="msg_username_or_email">Utilizador ou e-mail</string>
<string name="msg_password">Palavra-passe</string>
<string name="msg_name">Nome</string>
<string name="msg_email">E-mail</string>
<string name="msg_avatar_url">URL do avatar</string>
<string name="msg_or_continue_using_social_accounts">Ou continue utilizando uma conta social</string>
<string name="msg_new_user">Novo utilizador? %1$s</string>
<string name="msg_forgot__your_password">Esqueceu a sua palavra-passe?</string>
<string name="msg_reset">Repor</string>
<string name="msg_check_your_email_to_reset_your_password">E-mail enviado! Verifique a sua caixa de entrada para repor a sua palavra-passe.</string>
<string name="msg_invalid_email">Por favor introduza um endereço de e-mail válido</string>
<string name="msg_new_user_agreement">Ao prosseguir, você concorda com os nossos \n%1$s e %2$s</string>
<string name="msg_more_than_ninety_nine_unread_messages" translatable="false">99+</string>
<string name="msg_yesterday">Ontem</string>
<string name="msg_today">Hoje</string>
<string name="msg_message">Mensagem</string>
<string name="msg_this_room_is_read_only">Esta sala é apenas de leitura</string>
<string name="msg_invalid_2fa_code">Código 2FA inválido</string>
<string name="msg_invalid_file">Ficheiro inválido</string>
<string name="msg_invalid_server_url">URL de servidor inválido</string>
<string name="msg_content_description_log_in_using_facebook">Entre utilizando Facebook</string>
<string name="msg_content_description_log_in_using_github">Entre utilizando Github</string>
<string name="msg_content_description_log_in_using_google">Entre utilizando Google</string>
<string name="msg_content_description_log_in_using_linkedin">Entre utilizando LinkedIn</string>
<string name="msg_content_description_log_in_using_meteor">Entre utilizando Meteor</string>
<string name="msg_content_description_log_in_using_twitter">Entre utilizando Twitter</string>
<string name="msg_content_description_log_in_using_gitlab">Entre utilizando Gitlab</string>
<string name="msg_content_description_log_in_using_wordpress">Entre utilizando WordPress</string>
<string name="msg_content_description_send_message">Enviar mensagem</string>
<string name="msg_content_description_show_more_login_options">Mostrar mais opções de entrada</string>
<string name="msg_content_description_show_attachment_options">Mostrar opções de ficheiro</string>
<string name="msg_you">Você</string>
<string name="msg_unknown">Desconhecido</string>
<string name="msg_email_address">Endereço de E-mail</string>
<string name="msg_utc_offset">Deslocamento UTC</string>
<string name="msg_new_password">Introduza a nova palavra-passe</string>
<string name="msg_confirm_password">Confirme a nova palavra-passe</string>
<string name="msg_channel_name">Nome do canal</string>
<string name="msg_search">Pesquisar</string>
<string name="msg_unread_messages">Mensagens não lidas</string>
<string name="msg_preview_video">Vídeo</string>
<string name="msg_preview_audio">Audio</string>
<string name="msg_preview_photo">Foto</string>
<string name="msg_preview_file">Ficheiro</string>
<string name="msg_no_messages_yet">Nenhuma mensagem ainda</string>
<string name="msg_build">Compilação %1$d - %2$s - %3$s</string>
<string name="msg_update_app_version_in_order_to_continue">Versão do servidor desactualizada. Entre em contato com o administrador do servidor para atualizar a versão do servidor para continuar.</string>
<string name="msg_ver_not_recommended">
Parece que a versão do seu servidor está abaixo da versão recomendada, %1$s.\nAinda é possível entrar, mas você pode experimentar comportamentos inesperados.</string>
<string name="msg_ver_not_minimum">
Parece que a versão do seu servidor está abaixo da versão mínima exigida, %1$s.\nPor favor, actualize o seu servidor para entrar!
</string>
<string name="msg_no_chat_title">Nenhuma mensagem de chat</string>
<string name="msg_no_chat_description">Inicie uma conversa para ver as\nsuas mensagens aqui.</string>
<string name="msg_http_insecure">Quando utiliza HTTP você liga-se a um servidor inseguro. Não lhe recomendamos que faça isso.</string>
<string name="msg_error_checking_server_version">Ocorreu um erro ao verificar a versão do seu servidor, tente novamente</string>
<string name="msg_invalid_server_protocol">O protocolo seleccionado não é aceite por este servidor, tente utilizar HTTPS</string>
<string name="msg_image_saved_successfully">Imagem guardada na galeria</string>
<string name="msg_image_saved_failed">Falha ao guardar imagem</string>
<string name="msg_edited">(editada)</string>
<string name="msg_and">\u0020e\u0020</string>
<string name="msg_is_typing">\u0020está a escrever…</string>
<string name="msg_are_typing">\u0020estão a escrever…</string>
<string name="msg_several_users_are_typing">Varios utilizadores estão a escrever…</string>
<string name="msg_no_search_found">Não foram encontrados resultados</string>
<string name="msg_log_out">A terminar sessão…</string>
<string name="msg_upload_file">Enviar ficheiro</string>
<string name="msg_file_description">Descrição do ficheiro</string>
<string name="msg_send">Enviar</string>
<string name="msg_sent_attachment">Enviou um ficheiro</string>
<string name="msg_welcome_to_rocket_chat">Bem vindo(a) ao Rocket.Chat</string>
<string name="msg_team_communication">Comunicação de Equipa</string>
<string name="msg_login_with_email">Entre com <b>e-mail</b></string>
<string name="msg_create_account">Crie uma conta</string>
<string name="msg_continue_with_facebook">Continue com <b>Facebook</b></string>
<string name="msg_continue_with_github">Continue com <b>Github</b></string>
<string name="msg_continue_with_google">Continue com <b>Google</b></string>
<string name="msg_continue_with_linkedin">Continue com <b>Linkedin</b></string>
<string name="msg_continue_with_gitlab">Continue com <b>GitLab</b></string>
<string name="msg_continue_with_wordpress">Continue com <b>WordPress</b></string>
<string name="msg_two_factor_authentication">Autenticação 2FA</string>
<string name="msg__your_2fa_code">Qual é o seu código 2FA?</string>
<string name="msg_permalink_copied">Link permanente copiado</string>
<string name="msg_no_topic">Nenhum tópico adicionado</string>
<string name="msg_no_announcement">Nenhum anúncio adicionado</string>
<string name="msg_no_description">Nenhuma descrição adicionada</string>
<string name="msg_send_email">Enviar e-mail</string>
<string name="msg_android_app_support">Suporte à aplicação Android</string>
<string name="msg_unable_to_update_password">Não é possível atualizar a palavra-passe. Erro: %1$s</string>
<string name="msg_password_updated_successfully">Palavra-passe actualizada com sucesso</string>
<plurals name="msg_reacted_with_">
<item quantity="one">%1$s reagiu com %2$s</item>
<item quantity="other">%1$s reagiram com %2$s</item>
</plurals>
<!-- Create channel messages -->
<string name="msg_private_channel">Privado</string>
<string name="msg_public_channel">Público</string>
<string name="msg_private_channel_description">Apenas você e membros convidados podem entrar neste canal</string>
<string name="msg_public_channel_description">Todos podem entrar neste canal</string>
<string name="msg_ready_only_channel">Canal apenas de leitura</string>
<string name="msg_ready_only_channel_description">Apenas administradores podem escrever novas mensagens</string>
<string name="msg_invite_members">Convidar membros para o canal</string>
<string name="msg_member_already_added">Você já seleccionou este utilizador</string>
<string name="msg_member_not_found">Membro não encontrado</string>
<string name="msg_channel_created_successfully">Canal criado com sucesso</string>
<string name="msg_message_copied">Mensagem copiada</string>
<string name="msg_delete_message">Apagar mensagem</string>
<string name="msg_delete_description">Tem a certeza que deseja apagar esta mensagem?</string>
<string name="msg_view_more">mostrar mais</string>
<string name="msg_view_less">mostrar menos</string>
<string name="msg_muted_on_this_channel">Você está silenciado neste canal</string>
<!-- Preferences messages -->
<string name="msg_analytics_tracking">Acompanhamento de análise</string>
<string name="msg_send_analytics_tracking">Enviar estatísticas anónimas para ajudar a melhorar esta aplicação</string>
<string name="msg_do_not_send_analytics_tracking">Não enviar estatísticas anónimas para ajudar a melhorar esta aplicação</string>
<string name="msg_not_applicable_since_it_is_a_foss_version">Não aplicável, visto ser uma versão FOSS</string>
<!-- System messages -->
<string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string>
<string name="message_user_added_by">Utilizador %1$s adicionado por %2$s</string>
<string name="message_user_removed_by">Utilizador %1$s removido por %2$s</string>
<string name="message_user_left">Saiu do canal.</string>
<string name="message_user_joined_channel">Entrou no canal.</string>
<string name="message_welcome">Bem vindo(a) %s</string>
<string name="message_removed">Mensagem removida</string>
<string name="message_pinned">Afixou uma mensagem:</string>
<string name="message_muted">Utilizador %1$s silenciado por %2$s</string>
<string name="message_unmuted">Utilizador %2$s removeu o silêncio de %1$s</string>
<string name="message_role_add">%3$s deu estatuto de %2$s a %1$s</string>
<string name="message_role_removed">%3$s retirou o estatuto de %2$s a %1$s</string>
<string name="message_credentials_saved_successfully">Credenciais guardadas com sucesso</string>
<!-- Message actions -->
<string name="action_msg_reply">Responder</string>
<string name="action_msg_info">Informação da mensagem</string>
<string name="action_msg_edit">Editar</string>
<string name="action_msg_copy">Copiar</string>
<string name="action_msg_quote">Citar</string>
<string name="action_msg_delete">Apagar</string>
<string name="action_msg_pin">Afixar mensagem</string>
<string name="action_msg_unpin">Desafixar mensagem</string>
<string name="action_msg_star">Dar um estrela</string>
<string name="action_msg_unstar">Remover estrela</string>
<string name="action_msg_share">Partilhar</string>
<string name="action_title_editing">A editar mensagem</string>
<string name="action_msg_add_reaction">Adicionar reacção</string>
<string name="action_msg_copy_permalink">Copiar link permanente</string>
<string name="action_msg_report">Relatar</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">Edição não é permitida</string>
<string name="permission_deleting_not_allowed">A remoção não é permitida</string>
<string name="permission_pinning_not_allowed">Afixação não é permitida</string>
<string name="permission_starring_not_allowed">Dar estrelas não é permitido</string>
<!-- Search message -->
<string name="title_search_message">Pesquisar mensagem</string>
<!-- Favorite/Unfavorite chat room -->
<string name="title_favorite_chat">Marcar chat como favorito</string>
<string name="title_unfavorite_chat">Desmarcar chat como favorito</string>
<!-- Members List -->
<string name="title_members_list">Membros</string>
<!-- Mentions -->
<string name="msg_mentions">Menções</string>
<string name="msg_no_mention">Nenhuma menção</string>
<string name="msg_all_the_mentions_appear_here">Todas as menções\naparecem aqui</string>
<!-- Pinned Messages -->
<string name="title_pinned_messages">Mensagens Afixadas</string>
<string name="no_pinned_messages">Sem mensagens afixadas</string>
<string name="no_pinned_description">Todas as mensagens afixadas\naparecem aqui</string>
<!-- Favorite Messages -->
<string name="title_favorite_messages">Mensagens Favoritas</string>
<string name="no_favorite_messages">Nenhuma mensagem favorita</string>
<string name="no_favorite_description">Todas as mensagens favoritas\naparecem aqui</string>
<!-- Files -->
<string name="title_files">Ficheiros</string>
<string name="title_files_total">Ficheiros (%d)</string>
<string name="msg_no_files">Nenhum ficheiro</string>
<string name="msg_all_files_appear_here">Todos os ficheiros aparecem aqui</string>
<!-- Upload Messages -->
<string name="max_file_size_exceeded">O tamanho do ficheiro (%1$d bytes) excedeu o máximo permitido de %2$d bytes</string>
<!-- Socket status -->
<string name="status_connected">Ligado</string>
<string name="status_disconnected">Desligado</string>
<string name="status_connecting">A ligar</string>
<string name="status_authenticating">A autenticar</string>
<string name="status_disconnecting">A desligar</string>
<string name="status_waiting">A ligar dentro de %d segundos</string>
<!--Suggestions-->
<string name="suggest_all_description">Notifica todos os utilizadores nesta sala</string>
<string name="suggest_here_description">Notifica os utilizadores activos nesta sala</string>
<!-- Slash Commands -->
<string name="Slash_Gimme_Description">Adiciona ༼ つ ◕_◕ ༽つ antes da sua mensagem</string>
<string name="Slash_LennyFace_Description">Adiciona ( ͡° ͜ʖ ͡°) depois da sua mensagem</string>
<string name="Slash_Shrug_Description">Adiciona ¯\_(ツ)_/¯ depois da sua mensagem</string>
<string name="Slash_Tableflip_Description">Adiciona (╯°□°)╯︵ ┻━┻</string>
<string name="Slash_TableUnflip_Description">Adiciona ┬─┬ ノ( ゜-゜ノ)</string>
<string name="Create_A_New_Channel">Criar um novo canal</string>
<string name="Show_the_keyboard_shortcut_list">Mostra a lista de atalhos do teclado</string>
<string name="Invite_user_to_join_channel_all_from">Convida todos os utilizadores do [#canal] para entrar neste canal</string>
<string name="Invite_user_to_join_channel_all_to">Convida todos os utilizadores deste canal a entrar no [#canal]</string>
<string name="Archive">Arquivar</string>
<string name="Remove_someone_from_room">Remove alguém da sala</string>
<string name="Leave_the_current_channel">Sai do canal actual</string>
<string name="Displays_action_text">Escreve um texto de acção</string>
<string name="Direct_message_someone">Envia uma mensagem directa para alguém</string>
<string name="Mute_someone_in_room">Silencia alguém na sala</string>
<string name="Unmute_someone_in_room">Remove o silêncio de alguém na sala</string>
<string name="Invite_user_to_join_channel">Convida um utilizador a entrar neste canal</string>
<string name="Unarchive">Desarquivar</string>
<string name="Join_the_given_channel">Entra no canal especificado</string>
<string name="Guggy_Command_Description">Gera um GIF baseado no texto fornecido</string>
<string name="Slash_Topic_Description">Define o tópico</string>
<!-- Emoji message-->
<string name="msg_no_recent_emoji">Nenhum emojis recente</string>
<string name="alert_title_default_skin_tone">Tom de pele padrão</string>
<!-- Sorting and grouping-->
<string name="msg_sort">Ordenar</string>
<string name="dialog_sort_title">Ordenar por</string>
<string name="dialog_sort_by_alphabet">Alfabeticamente</string>
<string name="dialog_sort_by_activity">Actividade</string>
<string name="dialog_group_by_type">Agrupar por tipo</string>
<string name="dialog_group_favourites">Agrupar favoritos</string>
<string name="chatroom_header">Cabeçalho</string>
<!--ChatRooms Headers-->
<string name="header_favorite">Favoritos</string>
<string name="header_channel">Canais</string>
<string name="header_private_groups">Grupos Privados</string>
<string name="header_direct_messages">Mensagens Directas</string>
<string name="header_live_chats">Chats ao Vivo</string>
<string name="header_unknown">Desconhecido</string>
<!--Notifications-->
<string name="share_label">Editar mensagem partilhada</string>
<string name="notif_action_reply_hint">RESPONDER</string>
<string name="notif_error_sending">A resposta falhou. Tente novamente.</string>
<string name="notif_success_sending">Mensagem enviada para %1$s!</string>
<string name="read_by">Lida por</string>
<string name="message_information_title">Informação da Mensagem</string>
<string name="message_room_changed_privacy">Tipo de sala alterado para: %1$s por %2$s</string>
<string name="foss" translatable="false">(FOSS)</string>
<!-- User Details -->
<string name="timezone">Fuso Horário</string>
<string name="status">Estado</string>
<!-- Report -->
<string name="submit">Enviar</string>
<string name="required">*requerido</string>
<string name="report_sent">O seu relatório foi enviado!</string>
</resources>
...@@ -315,6 +315,7 @@ ...@@ -315,6 +315,7 @@
<string name="chatroom_header">Заголовок</string> <string name="chatroom_header">Заголовок</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">Каналы</string> <string name="header_channel">Каналы</string>
<string name="header_private_groups">Приватные каналы</string> <string name="header_private_groups">Приватные каналы</string>
<string name="header_direct_messages">Личная переписка</string> <string name="header_direct_messages">Личная переписка</string>
......
...@@ -320,6 +320,7 @@ ...@@ -320,6 +320,7 @@
<string name="chatroom_header">Başlık</string> <string name="chatroom_header">Başlık</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">Kanallar</string> <string name="header_channel">Kanallar</string>
<string name="header_private_groups">Gizli Gruplar</string> <string name="header_private_groups">Gizli Gruplar</string>
<string name="header_direct_messages">Direkt Mesajlar</string> <string name="header_direct_messages">Direkt Mesajlar</string>
......
...@@ -316,6 +316,7 @@ ...@@ -316,6 +316,7 @@
<string name="chatroom_header">Заголовок</string> <string name="chatroom_header">Заголовок</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">Канали</string> <string name="header_channel">Канали</string>
<string name="header_private_groups">Приватні канали</string> <string name="header_private_groups">Приватні канали</string>
<string name="header_direct_messages">Особисті повідомлення</string> <string name="header_direct_messages">Особисті повідомлення</string>
......
...@@ -315,6 +315,7 @@ ...@@ -315,6 +315,7 @@
<string name="chatroom_header">头部</string> <string name="chatroom_header">头部</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<string name="header_channel">频道</string> <string name="header_channel">频道</string>
<string name="header_private_groups">私人组</string> <string name="header_private_groups">私人组</string>
<string name="header_direct_messages">直接对话</string> <string name="header_direct_messages">直接对话</string>
......
...@@ -331,6 +331,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -331,6 +331,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="chatroom_header">Header</string> <string name="chatroom_header">Header</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string>
<string name="header_channel">Channels</string> <string name="header_channel">Channels</string>
<string name="header_private_groups">Private Groups</string> <string name="header_private_groups">Private Groups</string>
<string name="header_direct_messages">Direct Messages</string> <string name="header_direct_messages">Direct Messages</string>
......
...@@ -53,8 +53,15 @@ class DrawingActivity : DaggerAppCompatActivity(), DrawView { ...@@ -53,8 +53,15 @@ class DrawingActivity : DaggerAppCompatActivity(), DrawView {
} }
private fun setupDrawTools() { private fun setupDrawTools() {
image_draw_eraser.setOnClickListener { image_draw_eraser.setOnLongClickListener{
custom_draw_view.clearCanvas() custom_draw_view.clearCanvas()
return@setOnLongClickListener true
}
image_draw_eraser.setOnClickListener {
custom_draw_view.setColor(
ResourcesCompat.getColor(resources, R.color.color_white, null)
)
toggleDrawTools(draw_tools, false) toggleDrawTools(draw_tools, false)
} }
...@@ -111,6 +118,13 @@ class DrawingActivity : DaggerAppCompatActivity(), DrawView { ...@@ -111,6 +118,13 @@ class DrawingActivity : DaggerAppCompatActivity(), DrawView {
} }
private fun colorSelector() { private fun colorSelector() {
image_color_black.setOnClickListener {
custom_draw_view.setColor(
ResourcesCompat.getColor(resources, R.color.color_black, null)
)
scaleColorView(image_color_black)
}
image_color_red.setOnClickListener { image_color_red.setOnClickListener {
custom_draw_view.setColor( custom_draw_view.setColor(
ResourcesCompat.getColor(resources, R.color.color_red, null) ResourcesCompat.getColor(resources, R.color.color_red, null)
......
...@@ -42,7 +42,6 @@ class CustomDrawView(context: Context, attrs: AttributeSet) : View(context, attr ...@@ -42,7 +42,6 @@ class CustomDrawView(context: Context, attrs: AttributeSet) : View(context, attr
fun undo() { fun undo() {
if (mPaths.isEmpty() && mLastPaths.isNotEmpty()) { if (mPaths.isEmpty() && mLastPaths.isNotEmpty()) {
mPaths = mLastPaths.clone() as LinkedHashMap<MyPath, PaintOptions> mPaths = mLastPaths.clone() as LinkedHashMap<MyPath, PaintOptions>
mLastPaths.clear()
invalidate() invalidate()
return return
} }
......
package chat.rocket.android.util.extension package chat.rocket.android.util.extension
import android.content.Context
import android.os.Build
import android.widget.TextView
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
fun SearchView.onQueryTextListener(queryListener: (String) -> Unit) { fun SearchView.onQueryTextListener(queryListener: (String) -> Unit) {
...@@ -14,4 +17,12 @@ fun SearchView.onQueryTextListener(queryListener: (String) -> Unit) { ...@@ -14,4 +17,12 @@ fun SearchView.onQueryTextListener(queryListener: (String) -> Unit) {
return true return true
} }
}) })
}
fun TextView.setTextViewAppearance(context: Context, style: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setTextAppearance(style)
} else {
setTextAppearance(context, style)
}
} }
\ No newline at end of file
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