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

Merge branch 'develop' into fix-2062

parents 75011244 c452c7bb
...@@ -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(
......
...@@ -316,16 +316,18 @@ class ChatRoomPresenter @Inject constructor( ...@@ -316,16 +316,18 @@ class ChatRoomPresenter @Inject constructor(
fun sendMessage(chatRoomId: String, text: String, messageId: String?) { fun sendMessage(chatRoomId: String, text: String, messageId: String?) {
launchUI(strategy) { launchUI(strategy) {
try { try {
view.disableSendMessageButton()
// ignore message for now, will receive it on the stream // ignore message for now, will receive it on the stream
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,
...@@ -1293,10 +1295,8 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1293,10 +1295,8 @@ 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() {
localRepository.clear(draftKey) localRepository.clear(draftKey)
......
...@@ -259,7 +259,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -259,7 +259,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
} }
......
...@@ -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()) {
...@@ -112,3 +115,11 @@ private fun ChatRoomFragment.setupDetailsMenuItem(menu: Menu) { ...@@ -112,3 +115,11 @@ private fun ChatRoomFragment.setupDetailsMenuItem(menu: Menu) {
).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
...@@ -36,15 +36,30 @@ class RoomUiModelMapper( ...@@ -36,15 +36,30 @@ 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 }
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(HeaderItemHolder(roomType(room.chatRoom.type)))
} }
list.add(RoomItemHolder(map(room, showLastMessage))) list.add(RoomItemHolder(map(room, showLastMessage)))
lastType = room.chatRoom.type lastType = room.chatRoom.type
} }
} else {
rooms.forEach { room ->
list.add(RoomItemHolder(map(room, showLastMessage)))
}
}
return list return list
} }
...@@ -108,6 +123,7 @@ class RoomUiModelMapper( ...@@ -108,6 +123,7 @@ class RoomUiModelMapper(
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)
...@@ -140,6 +156,7 @@ class RoomUiModelMapper( ...@@ -140,6 +156,7 @@ 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,
...@@ -157,6 +174,7 @@ class RoomUiModelMapper( ...@@ -157,6 +174,7 @@ class RoomUiModelMapper(
private fun roomType(type: String): String { private fun roomType(type: String): String {
val resources = context.resources val resources = context.resources
return when (type) { return when (type) {
RoomType.CHANNEL -> resources.getString(R.string.header_channel) RoomType.CHANNEL -> resources.getString(R.string.header_channel)
RoomType.PRIVATE_GROUP -> resources.getString(R.string.header_private_groups) RoomType.PRIVATE_GROUP -> resources.getString(R.string.header_private_groups)
......
...@@ -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,
......
...@@ -2,6 +2,7 @@ package chat.rocket.android.chatrooms.presentation ...@@ -2,6 +2,7 @@ package chat.rocket.android.chatrooms.presentation
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.chatrooms.domain.FetchChatRoomsInteractor
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.model.ChatRoomEntity import chat.rocket.android.db.model.ChatRoomEntity
...@@ -116,6 +117,7 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -116,6 +117,7 @@ class ChatRoomsPresenter @Inject constructor(
retryIO("createDirectMessage($name)") { retryIO("createDirectMessage($name)") {
withTimeout(10000) { withTimeout(10000) {
createDirectMessage(name) createDirectMessage(name)
FetchChatRoomsInteractor(client, dbManager).refreshChatRooms()
} }
} }
val fromTo = mutableListOf(myself.id, id).apply { val fromTo = mutableListOf(myself.id, id).apply {
......
...@@ -22,14 +22,11 @@ import com.shopify.livedataktx.map ...@@ -22,14 +22,11 @@ import com.shopify.livedataktx.map
import com.shopify.livedataktx.nonNull import com.shopify.livedataktx.nonNull
import kotlinx.coroutines.experimental.android.UI import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.delay import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.isActive
import kotlinx.coroutines.experimental.launch import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.newSingleThreadContext import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.withContext import kotlinx.coroutines.experimental.withContext
import kotlinx.coroutines.experimental.yield
import timber.log.Timber import timber.log.Timber
import java.lang.IllegalArgumentException
import kotlin.coroutines.experimental.coroutineContext
class ChatRoomsViewModel( class ChatRoomsViewModel(
private val connectionManager: ConnectionManager, private val connectionManager: ConnectionManager,
...@@ -53,18 +50,11 @@ class ChatRoomsViewModel( ...@@ -53,18 +50,11 @@ class ChatRoomsViewModel(
// debounce, to not query while the user is writing // debounce, to not query while the user is writing
delay(200) delay(200)
// TODO - find a better way for cancellation checking
if (!coroutineContext.isActive) return@wrap
val rooms = repository.search(string).let { mapper.map(it, showLastMessage = this.showLastMessage) } val rooms = repository.search(string).let { mapper.map(it, showLastMessage = this.showLastMessage) }
data.postValue(rooms.toMutableList() + LoadingItemHolder()) data.postValue(rooms.toMutableList() + LoadingItemHolder())
yield()
if (!coroutineContext.isActive) return@wrap
val spotlight = spotlight(query.query)?.let { mapper.map(it, showLastMessage = this.showLastMessage) } val spotlight = spotlight(query.query)?.let { mapper.map(it, showLastMessage = this.showLastMessage) }
if (!coroutineContext.isActive) return@wrap yield()
spotlight?.let { spotlight?.let {
data.postValue(rooms.toMutableList() + spotlight) data.postValue(rooms.toMutableList() + spotlight)
}.ifNull { }.ifNull {
......
...@@ -38,6 +38,9 @@ import kotlinx.android.synthetic.main.activity_main.* ...@@ -38,6 +38,9 @@ import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.app_bar.* import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.nav_header.view.* import kotlinx.android.synthetic.main.nav_header.view.*
import javax.inject.Inject import javax.inject.Inject
import android.app.NotificationManager
import android.content.Context
private const val CURRENT_STATE = "current_state" private const val CURRENT_STATE = "current_state"
...@@ -90,6 +93,9 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, ...@@ -90,6 +93,9 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
presenter.toChatList(chatRoomId) presenter.toChatList(chatRoomId)
isFragmentAdded = true isFragmentAdded = true
} }
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE)
as NotificationManager
notificationManager.cancelAll()
} }
override fun onDestroy() { override fun onDestroy() {
......
...@@ -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
......
...@@ -82,7 +82,7 @@ class ProfilePresenter @Inject constructor( ...@@ -82,7 +82,7 @@ class ProfilePresenter @Inject constructor(
view.showLoading() view.showLoading()
try { try {
user?.id?.let { id -> user?.id?.let { id ->
retryIO { client.updateProfile(id, email, name, username) } retryIO { client.updateProfile(userId = id, email = email, name = name, username = username) }
view.showProfileUpdateSuccessfullyMessage() view.showProfileUpdateSuccessfullyMessage()
view.showProfile( view.showProfile(
serverUrl.avatarUrl(user.username ?: ""), serverUrl.avatarUrl(user.username ?: ""),
...@@ -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)
......
...@@ -293,19 +293,14 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -293,19 +293,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()
} }
} }
} }
...@@ -295,7 +295,7 @@ class ConnectionManager( ...@@ -295,7 +295,7 @@ class ConnectionManager(
val batch = ArrayList<T>(maxSize) val batch = ArrayList<T>(maxSize)
var deadline = 0L // deadline for sending this batch to callback block var deadline = 0L // deadline for sending this batch to callback block
while(true) { while(isActive) {
// when deadline is reached or size is exceeded, pass the batch to the callback block // when deadline is reached or size is exceeded, pass the batch to the callback block
val remainingTime = deadline - System.currentTimeMillis() val remainingTime = deadline - System.currentTimeMillis()
if (batch.isNotEmpty() && remainingTime <= 0 || batch.size >= maxSize) { if (batch.isNotEmpty() && remainingTime <= 0 || batch.size >= maxSize) {
...@@ -317,8 +317,6 @@ class ConnectionManager( ...@@ -317,8 +317,6 @@ class ConnectionManager(
// when timeout is reached just finish select, note: no timeout when batch is empty // when timeout is reached just finish select, note: no timeout when batch is empty
if (batch.isNotEmpty()) onTimeout(remainingTime.orZero()) {} if (batch.isNotEmpty()) onTimeout(remainingTime.orZero()) {}
} }
if (!isActive) break
} }
} }
} }
......
...@@ -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
...@@ -128,11 +129,12 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen ...@@ -128,11 +129,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) {
......
...@@ -5,6 +5,7 @@ import chat.rocket.common.RocketChatNetworkErrorException ...@@ -5,6 +5,7 @@ import chat.rocket.common.RocketChatNetworkErrorException
import kotlinx.coroutines.experimental.TimeoutCancellationException import kotlinx.coroutines.experimental.TimeoutCancellationException
import kotlinx.coroutines.experimental.delay import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.isActive import kotlinx.coroutines.experimental.isActive
import kotlinx.coroutines.experimental.yield
import timber.log.Timber import timber.log.Timber
import kotlin.coroutines.experimental.coroutineContext import kotlin.coroutines.experimental.coroutineContext
...@@ -21,20 +22,17 @@ suspend fun <T> retryIO( ...@@ -21,20 +22,17 @@ suspend fun <T> retryIO(
{ {
var currentDelay = initialDelay var currentDelay = initialDelay
repeat(times - 1) { currentTry -> repeat(times - 1) { currentTry ->
if (!coroutineContext.isActive) throw TimeoutCancellationException("job canceled") yield()
try { try {
return block() return block()
} catch (e: RocketChatNetworkErrorException) { } catch (e: RocketChatNetworkErrorException) {
Timber.d(e, "failed call($currentTry): $description") Timber.d(e, "failed call($currentTry): $description")
e.printStackTrace() e.printStackTrace()
} }
if (!coroutineContext.isActive) throw TimeoutCancellationException("job canceled")
delay(currentDelay) delay(currentDelay)
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
} }
yield()
if (!coroutineContext.isActive) throw TimeoutCancellationException("job canceled")
return block() // last attempt return block() // last attempt
} }
...@@ -48,19 +46,15 @@ suspend fun <T> retryDB( ...@@ -48,19 +46,15 @@ suspend fun <T> retryDB(
{ {
var currentDelay = initialDelay var currentDelay = initialDelay
repeat(times - 1) { currentTry -> repeat(times - 1) { currentTry ->
if (!coroutineContext.isActive) throw TimeoutCancellationException("job canceled")
try { try {
return block() return block()
} catch (e: SQLiteDatabaseLockedException) { } catch (e: SQLiteDatabaseLockedException) {
Timber.d(e, "failed call($currentTry): $description") Timber.d(e, "failed call($currentTry): $description")
e.printStackTrace() e.printStackTrace()
} }
if (!coroutineContext.isActive) throw TimeoutCancellationException("job canceled")
delay(currentDelay) delay(currentDelay)
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
} }
yield()
if (!coroutineContext.isActive) throw TimeoutCancellationException("job canceled")
return block() // last attempt return block() // last attempt
} }
\ No newline at end of file
<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"
......
<?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>
......
...@@ -319,6 +319,7 @@ ...@@ -319,6 +319,7 @@
<string name="chatroom_header">Entête</string> <string name="chatroom_header">Entête</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
<string name="header_favorite">Favorites</string><!-- TODO - Add proper translation -->
<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>
......
...@@ -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">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">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>
......
...@@ -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>
...@@ -332,7 +333,7 @@ ...@@ -332,7 +333,7 @@
<string name="message_room_changed_privacy">Тип канала изменен на: %1$s пользователем %2$s</string> <string name="message_room_changed_privacy">Тип канала изменен на: %1$s пользователем %2$s</string>
<!-- User Details --> <!-- User Details -->
<string name="timezone">Часовой поясe</string> <string name="timezone">Часовой пояс</string>
<!-- Report --> <!-- Report -->
<string name="submit">Отправить</string> <string name="submit">Отправить</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
} }
......
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