Unverified Commit cc83b9ea authored by Filipe Brito's avatar Filipe Brito Committed by GitHub

Merge branch 'develop' into viewpager-rtl

parents 8f8cb4c8 556733e8
...@@ -124,6 +124,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -124,6 +124,7 @@ class ChatRoomPresenter @Inject constructor(
private var lastState = manager.state private var lastState = manager.state
private var typingStatusList = arrayListOf<String>() private var typingStatusList = arrayListOf<String>()
private val roomChangesChannel = Channel<Room>(Channel.CONFLATED) private val roomChangesChannel = Channel<Room>(Channel.CONFLATED)
private var lastMessageId: String? = null
private lateinit var draftKey: String private lateinit var draftKey: String
fun setupChatRoom( fun setupChatRoom(
...@@ -223,6 +224,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -223,6 +224,7 @@ class ChatRoomPresenter @Inject constructor(
isBroadcast = chatIsBroadcast, isRoom = true isBroadcast = chatIsBroadcast, isRoom = true
) )
) )
lastMessageId = localMessages.firstOrNull()?.id
val lastSyncDate = messagesRepository.getLastSyncDate(chatRoomId) val lastSyncDate = messagesRepository.getLastSyncDate(chatRoomId)
if (oldMessages.isNotEmpty() && lastSyncDate != null) { if (oldMessages.isNotEmpty() && lastSyncDate != null) {
view.showMessages(oldMessages, clearDataSet) view.showMessages(oldMessages, clearDataSet)
...@@ -235,7 +237,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -235,7 +237,7 @@ class ChatRoomPresenter @Inject constructor(
} }
// TODO: For now we are marking the room as read if we can get the messages (I mean, no exception occurs) // TODO: For now we are marking the room as read if we can get the messages (I mean, no exception occurs)
// but should mark only when the user see the first unread message. // but should mark only when the user sees the first unread message.
markRoomAsRead(chatRoomId) markRoomAsRead(chatRoomId)
subscribeMessages(chatRoomId) subscribeMessages(chatRoomId)
...@@ -371,6 +373,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -371,6 +373,7 @@ class ChatRoomPresenter @Inject constructor(
throw ex throw ex
} }
} }
lastMessageId = id
} else { } else {
client.updateMessage(chatRoomId, messageId, text) client.updateMessage(chatRoomId, messageId, text)
} }
...@@ -1089,6 +1092,31 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1089,6 +1092,31 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun reactToLastMessage(text: String, roomId: String) {
launchUI(strategy) {
lastMessageId?.let { messageId ->
val emoji = text.substring(1).trimEnd()
if (emoji.length >= 2 && emoji.startsWith(":") && emoji.endsWith(":")) {
try {
retryIO("toggleEmoji($messageId, $emoji)") {
client.toggleReaction(messageId, emoji.removeSurrounding(":"))
}
logReactionEvent()
view.clearMessageComposition(true)
} catch (ex: RocketChatException) {
Timber.e(ex)
// emoji is not valid, post it
sendMessage(roomId, text, null)
}
} else {
sendMessage(roomId, text, null)
}
}.ifNull {
sendMessage(roomId, text, null)
}
}
}
private fun logReactionEvent() { private fun logReactionEvent() {
when { when {
roomTypeOf(chatRoomType) is RoomType.DirectMessage -> roomTypeOf(chatRoomType) is RoomType.DirectMessage ->
...@@ -1162,18 +1190,19 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1162,18 +1190,19 @@ class ChatRoomPresenter @Inject constructor(
sendMessage(roomId, text, null) sendMessage(roomId, text, null)
} else { } else {
view.disableSendMessageButton() view.disableSendMessageButton()
val command = text.split(" ") val index = text.indexOf(" ")
val name = command[0].substring(1) var name = ""
var params = "" var params = ""
command.forEachIndexed { index, param -> if (index >= 1) {
if (index > 0) { name = text.substring(1, index)
params += "$param " params = text.substring(index + 1).trim()
}
} }
val result = retryIO("runCommand($name, $params, $roomId)") { val result = retryIO("runCommand($name, $params, $roomId)") {
client.runCommand(Command(name, params), roomId) client.runCommand(Command(name, params), roomId)
} }
if (!result) { if (result) {
view.clearMessageComposition(true)
} else {
// failed, command is not valid so post it // failed, command is not valid so post it
sendMessage(roomId, text, null) sendMessage(roomId, text, null)
} }
...@@ -1251,8 +1280,8 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1251,8 +1280,8 @@ class ChatRoomPresenter @Inject constructor(
launchUI(strategy) { launchUI(strategy) {
val viewModelStreamedMessage = mapper.map( val viewModelStreamedMessage = mapper.map(
streamedMessage, RoomUiModel( streamedMessage, RoomUiModel(
roles = chatRoles, isBroadcast = chatIsBroadcast, isRoom = true roles = chatRoles, isBroadcast = chatIsBroadcast, isRoom = true
) )
) )
val roomMessages = messagesRepository.getByRoomId(streamedMessage.roomId) val roomMessages = messagesRepository.getByRoomId(streamedMessage.roomId)
val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id } val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id }
...@@ -1286,6 +1315,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1286,6 +1315,7 @@ class ChatRoomPresenter @Inject constructor(
fun clearDraftMessage() { fun clearDraftMessage() {
localRepository.clear(draftKey) localRepository.clear(draftKey)
} }
/** /**
* Get unfinished message from local repository, when user left chat room without * Get unfinished message from local repository, when user left chat room without
* sending a message and now the user is back. * sending a message and now the user is back.
......
...@@ -148,10 +148,14 @@ private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message" ...@@ -148,10 +148,14 @@ private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message"
class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener, class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener,
ChatRoomAdapter.OnActionSelected, Drawable.Callback { ChatRoomAdapter.OnActionSelected, Drawable.Callback {
@Inject lateinit var presenter: ChatRoomPresenter @Inject
@Inject lateinit var parser: MessageParser lateinit var presenter: ChatRoomPresenter
@Inject lateinit var analyticsManager: AnalyticsManager @Inject
@Inject lateinit var navigator: ChatRoomNavigator lateinit var parser: MessageParser
@Inject
lateinit var analyticsManager: AnalyticsManager
@Inject
lateinit var navigator: ChatRoomNavigator
private lateinit var adapter: ChatRoomAdapter private lateinit var adapter: ChatRoomAdapter
internal lateinit var chatRoomId: String internal lateinit var chatRoomId: String
private lateinit var chatRoomName: String private lateinit var chatRoomName: String
...@@ -472,14 +476,15 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -472,14 +476,15 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
} }
override fun sendMessage(text: String) { override fun sendMessage(text: String) {
ui { ui {
if (!text.isBlank()) { if (!text.isBlank()) {
if (!text.startsWith("/")) { if (text.startsWith("/")) {
presenter.sendMessage(chatRoomId, text, editingMessageId)
} else {
presenter.runCommand(text, chatRoomId) presenter.runCommand(text, chatRoomId)
} else if (text.startsWith("+")) {
presenter.reactToLastMessage(text, chatRoomId)
} else {
presenter.sendMessage(chatRoomId, text, editingMessageId)
} }
} }
} }
...@@ -524,7 +529,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -524,7 +529,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
} }
override fun clearMessageComposition(deleteMessage: Boolean) { override fun clearMessageComposition(deleteMessage: Boolean) {
ui { ui {
citation = null citation = null
...@@ -896,7 +900,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -896,7 +900,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_take_a_photo.setOnClickListener { button_take_a_photo.setOnClickListener {
// Check for camera permission // Check for camera permission
context?.let { context?.let {
if(hasCameraPermission(it)) { if (hasCameraPermission(it)) {
dispatchTakePictureIntent() dispatchTakePictureIntent()
} else { } else {
getCameraPermission(this) getCameraPermission(this)
...@@ -964,7 +968,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -964,7 +968,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
grantResults: IntArray grantResults: IntArray
) { ) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when(requestCode) { when (requestCode) {
AndroidPermissionsHelper.CAMERA_CODE -> { AndroidPermissionsHelper.CAMERA_CODE -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted // permission was granted
......
package chat.rocket.android.server.infrastructure package chat.rocket.android.server.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import java.util.*
private const val CURRENT_LANGUAGE = "current_language" private const val CURRENT_LANGUAGE = "current_language"
private const val CURRENT_LANGUAGE_COUNTRY = "current_language_country" private const val CURRENT_LANGUAGE_COUNTRY = "current_language_country"
...@@ -16,10 +17,10 @@ class SharedPrefsCurrentLanguageRepository(private val preferences: SharedPrefer ...@@ -16,10 +17,10 @@ class SharedPrefsCurrentLanguageRepository(private val preferences: SharedPrefer
} }
override fun getLanguage(): String? { override fun getLanguage(): String? {
return preferences.getString(CURRENT_LANGUAGE, "") return preferences.getString(CURRENT_LANGUAGE, Locale.getDefault().language)
} }
override fun getCountry(): String? { override fun getCountry(): String? {
return preferences.getString(CURRENT_LANGUAGE_COUNTRY, "") return preferences.getString(CURRENT_LANGUAGE_COUNTRY, Locale.getDefault().country)
} }
} }
package chat.rocket.android.settings.presentation package chat.rocket.android.settings.presentation
import android.content.Context
import android.os.Build
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManagerFactory import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.helper.UserHelper import chat.rocket.android.helper.UserHelper
import chat.rocket.android.main.presentation.MainNavigator import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.domain.AnalyticsTrackingInteractor import chat.rocket.android.server.domain.AnalyticsTrackingInteractor
import chat.rocket.android.server.domain.GetCurrentLanguageInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.PermissionsInteractor import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.RemoveAccountInteractor import chat.rocket.android.server.domain.RemoveAccountInteractor
...@@ -27,6 +28,7 @@ import chat.rocket.core.internal.rest.serverInfo ...@@ -27,6 +28,7 @@ import chat.rocket.core.internal.rest.serverInfo
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import timber.log.Timber import timber.log.Timber
import java.util.*
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named import javax.inject.Named
...@@ -40,11 +42,11 @@ class SettingsPresenter @Inject constructor( ...@@ -40,11 +42,11 @@ class SettingsPresenter @Inject constructor(
private val tokenRepository: TokenRepository, private val tokenRepository: TokenRepository,
private val permissions: PermissionsInteractor, private val permissions: PermissionsInteractor,
private val rocketChatClientFactory: RocketChatClientFactory, private val rocketChatClientFactory: RocketChatClientFactory,
private val saveLanguageInteractor: SaveCurrentLanguageInteractor,
getCurrentServerInteractor: GetCurrentServerInteractor, getCurrentServerInteractor: GetCurrentServerInteractor,
removeAccountInteractor: RemoveAccountInteractor, removeAccountInteractor: RemoveAccountInteractor,
databaseManagerFactory: DatabaseManagerFactory, databaseManagerFactory: DatabaseManagerFactory,
connectionManagerFactory: ConnectionManagerFactory, connectionManagerFactory: ConnectionManagerFactory
private val saveLanguageInteractor: SaveCurrentLanguageInteractor
) : CheckServerPresenter( ) : CheckServerPresenter(
strategy = strategy, strategy = strategy,
factory = rocketChatClientFactory, factory = rocketChatClientFactory,
...@@ -93,7 +95,6 @@ class SettingsPresenter @Inject constructor( ...@@ -93,7 +95,6 @@ class SettingsPresenter @Inject constructor(
fun enableAnalyticsTracking(isEnabled: Boolean) { fun enableAnalyticsTracking(isEnabled: Boolean) {
analyticsTrackingInteractor.save(isEnabled) analyticsTrackingInteractor.save(isEnabled)
} }
fun logout() { fun logout() {
...@@ -127,6 +128,14 @@ class SettingsPresenter @Inject constructor( ...@@ -127,6 +128,14 @@ class SettingsPresenter @Inject constructor(
} }
} }
fun getCurrentLocale(context: Context): Locale {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
context.resources.configuration.locales.get(0)
} else {
context.resources.configuration.locale
}
}
fun saveLocale(language: String, country: String? = null) { fun saveLocale(language: String, country: String? = null) {
saveLanguageInteractor.save(language, country) saveLanguageInteractor.save(language, country)
} }
......
...@@ -35,8 +35,28 @@ internal const val TAG_SETTINGS_FRAGMENT = "SettingsFragment" ...@@ -35,8 +35,28 @@ internal const val TAG_SETTINGS_FRAGMENT = "SettingsFragment"
fun newInstance(): Fragment = SettingsFragment() fun newInstance(): Fragment = SettingsFragment()
class SettingsFragment : Fragment(), SettingsView, AppLanguageView { class SettingsFragment : Fragment(), SettingsView, AppLanguageView {
@Inject lateinit var analyticsManager: AnalyticsManager @Inject
@Inject lateinit var presenter: SettingsPresenter lateinit var analyticsManager: AnalyticsManager
@Inject
lateinit var presenter: SettingsPresenter
private val locales = arrayListOf(
"en",
"ar",
"de",
"es",
"fa",
"fr",
"hi,IN",
"it",
"ja",
"pt,BR",
"pt,PT",
"ru,RU",
"tr",
"uk",
"zh,CN",
"zh,TW"
)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -163,28 +183,33 @@ class SettingsFragment : Fragment(), SettingsView, AppLanguageView { ...@@ -163,28 +183,33 @@ class SettingsFragment : Fragment(), SettingsView, AppLanguageView {
private fun changeLanguage() { private fun changeLanguage() {
context?.let { context?.let {
val selectedLocale = presenter.getCurrentLocale(it)
var localeIndex = -1
locales.forEachIndexed { index, locale ->
val array = locale.split(",")
val language = array[0]
val country = if (array.size > 1) array[1] else ""
// If language and country are specified, return the respective locale, else return
// the first locale found if the language is as specified regardless of the country.
if (language == selectedLocale.language) {
if (country == selectedLocale.country) {
localeIndex = index
return@forEachIndexed
} else if (localeIndex == -1) {
localeIndex = index
}
}
}
AlertDialog.Builder(it) AlertDialog.Builder(it)
.setTitle(R.string.title_choose_language) .setTitle(R.string.title_choose_language)
.setSingleChoiceItems( .setSingleChoiceItems(
resources.getStringArray(R.array.languages), -1 resources.getStringArray(R.array.languages), localeIndex
) { dialog, option -> ) { dialog, option ->
when (option) { val array = locales[option].split(",")
0 -> updateLanguage("en") if (array.size > 1) {
1 -> updateLanguage("ar") updateLanguage(array[0], array[1])
2 -> updateLanguage("de") } else {
3 -> updateLanguage("es") updateLanguage(array[0])
4 -> updateLanguage("fa")
5 -> updateLanguage("fr")
6 -> updateLanguage("hi", "IN")
7 -> updateLanguage("it")
8 -> updateLanguage("ja")
9 -> updateLanguage("pt", "BR")
10 -> updateLanguage("pt", "PT")
11 -> updateLanguage("ru", "RU")
12 -> updateLanguage("tr")
13 -> updateLanguage("uk")
14 -> updateLanguage("zh", "CN")
15 -> updateLanguage("zh", "TW")
} }
dialog.dismiss() dialog.dismiss()
} }
...@@ -231,4 +256,4 @@ class SettingsFragment : Fragment(), SettingsView, AppLanguageView { ...@@ -231,4 +256,4 @@ class SettingsFragment : Fragment(), SettingsView, AppLanguageView {
.show() .show()
} }
} }
} }
\ No newline at end of file
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<string name="title_authentication">Login Daten prüfen</string> <string name="title_authentication">Login Daten prüfen</string>
<string name="title_legal_terms">Legal Terms</string> <string name="title_legal_terms">Legal Terms</string>
<string name="title_chats">Chats</string> <string name="title_chats">Chats</string>
<string name="title_choose_language">Choose Language</string> <!-- TODO Add translation --> <string name="title_choose_language">Sprache wählen</string>
<string name="title_profile">Profil</string> <string name="title_profile">Profil</string>
<string name="title_members">Benutzer</string> <string name="title_members">Benutzer</string>
<string name="title_counted_members">Benutzer (%d)</string> <string name="title_counted_members">Benutzer (%d)</string>
...@@ -77,23 +77,23 @@ ...@@ -77,23 +77,23 @@
<string name="msg_delete_account">Konto löschen</string> <string name="msg_delete_account">Konto löschen</string>
<string name="msg_change_status">Status ändern</string> <string name="msg_change_status">Status ändern</string>
<string-array name="languages"> <!-- TODO Add translations --> <string-array name="languages">
<item>English</item> <item>Englisch</item>
<item>Arabic</item> <item>Arabisch</item>
<item>German</item> <item>Deutsch</item>
<item>Spanish</item> <item>Spanisch</item>
<item>Persian</item> <item>Persisch</item>
<item>French</item> <item>Französisch</item>
<item>Hindi (IN)</item> <item>Hindi (IN)</item>
<item>Italian</item> <item>Italienisch</item>
<item>Japanese</item> <item>Japanisch</item>
<item>Portuguese (BR)</item> <item>Portugiesisch (BR)</item>
<item>Portuguese (PT)</item> <item>Portugiesisch (PT)</item>
<item>Russian (RU)</item> <item>Russisch (RU)</item>
<item>Turkish</item> <item>Türkisch</item>
<item>Ukrainian</item> <item>Ukrainisch</item>
<item>Chinese (CN)</item> <item>Chinesisch (CN)</item>
<item>Chinese (TW)</item> <item>Chinesisch (TW)</item>
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
...@@ -360,9 +360,8 @@ ...@@ -360,9 +360,8 @@
<!-- User Details --> <!-- User Details -->
<string name="timezone">Zeitzone</string> <string name="timezone">Zeitzone</string>
<string name="status">Status: %1$s</string> <!-- TODO Translate --> <string name="status">Status: %1$s</string>
<string name="user_detail_status">Status</string> <!-- TODO Translate --> <string name="user_detail_status">Status</string>
<!-- Report --> <!-- Report -->
<string name="submit">Senden</string> <string name="submit">Senden</string>
<string name="required">*erforderlich</string> <string name="required">*erforderlich</string>
......
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