Commit 2652ba64 authored by Govind Dixit's avatar Govind Dixit

Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.Android into develop

parents 1c5e33fe a830e92c
...@@ -16,7 +16,7 @@ android { ...@@ -16,7 +16,7 @@ android {
applicationId "chat.rocket.android" applicationId "chat.rocket.android"
minSdkVersion versions.minSdk minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk
versionCode 2051 versionCode 2052
versionName "3.2.0" versionName "3.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
......
...@@ -93,6 +93,16 @@ ...@@ -93,6 +93,16 @@
android:name=".settings.password.ui.PasswordActivity" android:name=".settings.password.ui.PasswordActivity"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme" />
<activity
android:name=".userdetails.ui.UserDetailsActivity"
android:theme="@style/AppTheme"
android:windowSoftInputMode="stateAlwaysHidden">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".chatroom.ui.ChatRoomActivity" />
</activity>
<receiver <receiver
android:name=".push.DirectReplyReceiver" android:name=".push.DirectReplyReceiver"
android:enabled="true" android:enabled="true"
......
...@@ -19,7 +19,6 @@ import dagger.android.AndroidInjector ...@@ -19,7 +19,6 @@ import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.app_bar.* import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.coroutines.experimental.Job
import javax.inject.Inject import javax.inject.Inject
class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector { class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
...@@ -27,7 +26,6 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector { ...@@ -27,7 +26,6 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment> lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
@Inject @Inject
lateinit var presenter: AuthenticationPresenter lateinit var presenter: AuthenticationPresenter
val job = Job()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this) AndroidInjection.inject(this)
......
...@@ -251,6 +251,9 @@ class ChatRoomAdapter( ...@@ -251,6 +251,9 @@ class ChatRoomAdapter(
R.id.action_message_permalink -> { R.id.action_message_permalink -> {
actionSelectListener?.copyPermalink(id) actionSelectListener?.copyPermalink(id)
} }
R.id.action_message_report -> {
actionSelectListener?.reportMessage(id)
}
else -> { else -> {
TODO("Not implemented") TODO("Not implemented")
} }
...@@ -260,16 +263,29 @@ class ChatRoomAdapter( ...@@ -260,16 +263,29 @@ class ChatRoomAdapter(
} }
interface OnActionSelected { interface OnActionSelected {
fun showMessageInfo(id: String) fun showMessageInfo(id: String)
fun citeMessage(roomName: String, roomType: String, messageId: String, mentionAuthor: Boolean) fun citeMessage(roomName: String, roomType: String, messageId: String, mentionAuthor: Boolean)
fun copyMessage(id: String) fun copyMessage(id: String)
fun editMessage(roomId: String, messageId: String, text: String) fun editMessage(roomId: String, messageId: String, text: String)
fun toogleStar(id: String, star: Boolean) fun toogleStar(id: String, star: Boolean)
fun tooglePin(id: String, pin: Boolean) fun tooglePin(id: String, pin: Boolean)
fun deleteMessage(roomId: String, id: String) fun deleteMessage(roomId: String, id: String)
fun showReactions(id: String) fun showReactions(id: String)
fun openDirectMessage(roomName: String, message: String) fun openDirectMessage(roomName: String, message: String)
fun sendMessage(chatRoomId: String, text: String) fun sendMessage(chatRoomId: String, text: String)
fun copyPermalink(id: String) fun copyPermalink(id: String)
fun reportMessage(id: String)
} }
} }
package chat.rocket.android.chatroom.adapter package chat.rocket.android.chatroom.adapter
import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.text.Spannable import android.text.Spannable
...@@ -10,6 +11,7 @@ import androidx.core.view.isVisible ...@@ -10,6 +11,7 @@ import androidx.core.view.isVisible
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.uimodel.MessageUiModel import chat.rocket.android.chatroom.uimodel.MessageUiModel
import chat.rocket.android.emoji.EmojiReactionListener import chat.rocket.android.emoji.EmojiReactionListener
import chat.rocket.android.userdetails.ui.userDetailsIntent
import chat.rocket.core.model.isSystemMessage import chat.rocket.core.model.isSystemMessage
import com.bumptech.glide.load.resource.gif.GifDrawable import com.bumptech.glide.load.resource.gif.GifDrawable
import kotlinx.android.synthetic.main.avatar.view.* import kotlinx.android.synthetic.main.avatar.view.*
...@@ -70,9 +72,25 @@ class MessageViewHolder( ...@@ -70,9 +72,25 @@ class MessageViewHolder(
) )
read_receipt_view.isVisible = true read_receipt_view.isVisible = true
} }
val senderId = data.message.sender?.id
val subscriptionId = data.subscriptionId
text_sender.setOnClickListener {
toUserDetails(context, senderId, subscriptionId)
}
image_avatar.setOnClickListener {
toUserDetails(context, senderId, subscriptionId)
}
} }
} }
private fun toUserDetails(context: Context, userId: String?, subscriptionId: String) {
userId?.let { context.startActivity(context.userDetailsIntent(it, subscriptionId)) }
}
override fun unscheduleDrawable(who: Drawable?, what: Runnable?) { override fun unscheduleDrawable(who: Drawable?, what: Runnable?) {
with(itemView) { with(itemView) {
text_content.removeCallbacks(what) text_content.removeCallbacks(what)
......
...@@ -9,9 +9,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy ...@@ -9,9 +9,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.ChatRoomDao import chat.rocket.android.db.ChatRoomDao
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.db.UserDao import chat.rocket.android.db.UserDao
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetCurrentUserInteractor import chat.rocket.android.server.domain.GetCurrentUserInteractor
import chat.rocket.android.server.domain.PermissionsInteractor import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
......
...@@ -66,4 +66,4 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) { ...@@ -66,4 +66,4 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
activity.startActivity(activity.messageInformationIntent(messageId = messageId)) activity.startActivity(activity.messageInformationIntent(messageId = messageId))
activity.overridePendingTransition(R.anim.open_enter, R.anim.open_exit) activity.overridePendingTransition(R.anim.open_enter, R.anim.open_exit)
} }
} }
\ No newline at end of file
...@@ -60,6 +60,7 @@ import chat.rocket.core.internal.rest.joinChat ...@@ -60,6 +60,7 @@ import chat.rocket.core.internal.rest.joinChat
import chat.rocket.core.internal.rest.markAsRead import chat.rocket.core.internal.rest.markAsRead
import chat.rocket.core.internal.rest.messages import chat.rocket.core.internal.rest.messages
import chat.rocket.core.internal.rest.pinMessage import chat.rocket.core.internal.rest.pinMessage
import chat.rocket.core.internal.rest.reportMessage
import chat.rocket.core.internal.rest.runCommand import chat.rocket.core.internal.rest.runCommand
import chat.rocket.core.internal.rest.searchMessages import chat.rocket.core.internal.rest.searchMessages
import chat.rocket.core.internal.rest.sendMessage import chat.rocket.core.internal.rest.sendMessage
...@@ -373,6 +374,19 @@ class ChatRoomPresenter @Inject constructor( ...@@ -373,6 +374,19 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun reportMessage(messageId: String, description: String) {
launchUI(strategy) {
try {
retryIO("reportMessage($messageId, $description)") {
client.reportMessage(messageId = messageId, description = description)
}
view.showMessage(R.string.report_sent)
} catch (ex: RocketChatException) {
Timber.e(ex)
}
}
}
fun selectFile() { fun selectFile() {
view.showFileSelection(settings.uploadMimeTypeFilter()) view.showFileSelection(settings.uploadMimeTypeFilter())
} }
......
...@@ -68,17 +68,18 @@ import chat.rocket.android.helper.ImageHelper ...@@ -68,17 +68,18 @@ import chat.rocket.android.helper.ImageHelper
import chat.rocket.android.helper.KeyboardHelper import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.MessageParser import chat.rocket.android.helper.MessageParser
import chat.rocket.android.util.extension.asObservable import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extension.createImageFile
import chat.rocket.android.util.extensions.circularRevealOrUnreveal import chat.rocket.android.util.extensions.circularRevealOrUnreveal
import chat.rocket.android.util.extensions.content
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.getBitmpap
import chat.rocket.android.util.extensions.hideKeyboard import chat.rocket.android.util.extensions.hideKeyboard
import chat.rocket.android.util.extensions.inflate import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.rotateBy import chat.rocket.android.util.extensions.rotateBy
import chat.rocket.android.util.extensions.showToast import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.extension.createImageFile
import chat.rocket.android.util.extensions.getBitmpap
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
import chat.rocket.core.internal.realtime.socket.model.State import chat.rocket.core.internal.realtime.socket.model.State
...@@ -86,19 +87,16 @@ import dagger.android.support.AndroidSupportInjection ...@@ -86,19 +87,16 @@ import dagger.android.support.AndroidSupportInjection
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.emoji_image_row_item.*
import kotlinx.android.synthetic.main.emoji_image_row_item.view.* import kotlinx.android.synthetic.main.emoji_image_row_item.view.*
import kotlinx.android.synthetic.main.emoji_row_item.*
import kotlinx.android.synthetic.main.emoji_row_item.view.* import kotlinx.android.synthetic.main.emoji_row_item.view.*
import kotlinx.android.synthetic.main.fragment_chat_room.* import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_attachment_options.* import kotlinx.android.synthetic.main.message_attachment_options.*
import kotlinx.android.synthetic.main.message_composer.* import kotlinx.android.synthetic.main.message_composer.*
import kotlinx.android.synthetic.main.message_list.* import kotlinx.android.synthetic.main.message_list.*
import kotlinx.android.synthetic.main.reaction_praises_list_item.view.*
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import kotlinx.android.synthetic.main.reaction_praises_list_item.*
import kotlinx.android.synthetic.main.reaction_praises_list_item.view.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject import javax.inject.Inject
...@@ -144,7 +142,7 @@ private const val BUNDLE_CHAT_ROOM_IS_CREATOR = "chat_room_is_creator" ...@@ -144,7 +142,7 @@ private const val BUNDLE_CHAT_ROOM_IS_CREATOR = "chat_room_is_creator"
private const val BUNDLE_CHAT_ROOM_IS_FAVORITE = "chat_room_is_favorite" private const val BUNDLE_CHAT_ROOM_IS_FAVORITE = "chat_room_is_favorite"
private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message" private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message"
internal const val MENU_ACTION_FAVORITE_UNFAVORITE_CHAT = 1 internal const val MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT = 1
internal const val MENU_ACTION_SHOW_DETAILS = 2 internal const val MENU_ACTION_SHOW_DETAILS = 2
class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener, class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener,
...@@ -842,9 +840,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -842,9 +840,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} else { } else {
input_container.isVisible = true input_container.isVisible = true
text_room_is_read_only.isVisible = false text_room_is_read_only.isVisible = false
button_send.isVisible = false
button_show_attachment_options.alpha = 1f button_show_attachment_options.alpha = 1f
button_show_attachment_options.isVisible = true
activity?.supportFragmentManager?.registerFragmentLifecycleCallbacks( activity?.supportFragmentManager?.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() { object : FragmentManager.FragmentLifecycleCallbacks() {
...@@ -862,7 +858,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -862,7 +858,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
) )
subscribeComposeTextMessage() subscribeComposeTextMessage()
getUnfinishedMessage()
emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container)) emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container))
emojiKeyboardPopup.listener = this emojiKeyboardPopup.listener = this
text_message.listener = object : ComposerEditText.ComposerEditTextListener { text_message.listener = object : ComposerEditText.ComposerEditTextListener {
...@@ -1172,4 +1167,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -1172,4 +1167,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override fun sendMessage(chatRoomId: String, text: String) { override fun sendMessage(chatRoomId: String, text: String) {
presenter.sendMessage(chatRoomId, text, null) presenter.sendMessage(chatRoomId, text, null)
} }
override fun reportMessage(id: String) {
presenter.reportMessage(messageId = id,
description = "This message was reported by a user from the Android app")
}
} }
...@@ -17,7 +17,7 @@ internal fun ChatRoomFragment.setupMenu(menu: Menu) { ...@@ -17,7 +17,7 @@ internal fun ChatRoomFragment.setupMenu(menu: Menu) {
internal fun ChatRoomFragment.setOnMenuItemClickListener(item: MenuItem) { internal fun ChatRoomFragment.setOnMenuItemClickListener(item: MenuItem) {
when (item.itemId) { when (item.itemId) {
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT -> presenter.toggleFavoriteChatRoom( MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT -> presenter.toggleFavoriteChatRoom(
chatRoomId, chatRoomId,
isFavorite isFavorite
) )
...@@ -87,7 +87,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) { ...@@ -87,7 +87,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) {
if (isFavorite) { if (isFavorite) {
menu.add( menu.add(
Menu.NONE, Menu.NONE,
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT, MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT,
Menu.NONE, Menu.NONE,
R.string.title_unfavorite_chat R.string.title_unfavorite_chat
).setIcon(R.drawable.ic_star_yellow_24dp) ).setIcon(R.drawable.ic_star_yellow_24dp)
...@@ -95,7 +95,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) { ...@@ -95,7 +95,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) {
} else { } else {
menu.add( menu.add(
Menu.NONE, Menu.NONE,
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT, MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT,
Menu.NONE, Menu.NONE,
R.string.title_favorite_chat R.string.title_favorite_chat
).setIcon(R.drawable.ic_star_border_white_24dp) ).setIcon(R.drawable.ic_star_border_white_24dp)
......
...@@ -21,7 +21,8 @@ data class MessageUiModel( ...@@ -21,7 +21,8 @@ data class MessageUiModel(
var isFirstUnread: Boolean, var isFirstUnread: Boolean,
override var isTemporary: Boolean = false, override var isTemporary: Boolean = false,
override var menuItemsToHide: MutableList<Int> = mutableListOf(), override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var permalink: String override var permalink: String,
val subscriptionId: String
) : BaseMessageUiModel<Message> { ) : BaseMessageUiModel<Message> {
override val viewType: Int override val viewType: Int
get() = BaseUiModel.ViewType.MESSAGE.viewType get() = BaseUiModel.ViewType.MESSAGE.viewType
......
...@@ -456,7 +456,8 @@ class UiModelMapper @Inject constructor( ...@@ -456,7 +456,8 @@ class UiModelMapper @Inject constructor(
messageId = message.id, avatar = avatar!!, time = time, senderName = sender, messageId = message.id, avatar = avatar!!, time = time, senderName = sender,
content = content, isPinned = message.pinned, currentDayMarkerText = dayMarkerText, content = content, isPinned = message.pinned, currentDayMarkerText = dayMarkerText,
showDayMarker = false, reactions = getReactions(message), isFirstUnread = false, showDayMarker = false, reactions = getReactions(message), isFirstUnread = false,
preview = preview, isTemporary = !synced, unread = unread, permalink = permalink) preview = preview, isTemporary = !synced, unread = unread, permalink = permalink,
subscriptionId = chatRoom.subscriptionId)
} }
private fun mapMessagePreview(message: Message): Message { private fun mapMessagePreview(message: Message): Message {
......
...@@ -2,9 +2,6 @@ package chat.rocket.android.chatrooms.adapter ...@@ -2,9 +2,6 @@ package chat.rocket.android.chatrooms.adapter
import android.app.Application import android.app.Application
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import androidx.core.content.ContextCompat
import androidx.core.text.bold
import androidx.core.text.color
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.db.model.ChatRoom import chat.rocket.android.db.model.ChatRoom
...@@ -32,18 +29,13 @@ class RoomUiModelMapper( ...@@ -32,18 +29,13 @@ class RoomUiModelMapper(
private val serverUrl: String, private val serverUrl: String,
private val permissions: PermissionsInteractor private val permissions: PermissionsInteractor
) { ) {
private val nameUnreadColor = ContextCompat.getColor(context, R.color.colorPrimaryText) private val currentUser by lazy { userInteractor.get() }
private val nameColor = ContextCompat.getColor(context, R.color.colorSecondaryText)
private val dateUnreadColor = ContextCompat.getColor(context, R.color.colorAccent)
private val dateColor = ContextCompat.getColor(context, R.color.colorSecondaryText)
private val messageUnreadColor = ContextCompat.getColor(context, android.R.color.primary_text_light)
private val messageColor = ContextCompat.getColor(context, R.color.colorSecondaryText)
private val currentUser by lazy {
userInteractor.get()
}
fun map(rooms: List<ChatRoom>, grouped: Boolean = false, showLastMessage: Boolean = true): List<ItemHolder<*>> { fun map(
rooms: List<ChatRoom>,
grouped: Boolean = false,
showLastMessage: Boolean = true
): List<ItemHolder<*>> {
val list = ArrayList<ItemHolder<*>>(rooms.size + 4) val list = ArrayList<ItemHolder<*>>(rooms.size + 4)
var lastType: String? = null var lastType: String? = null
rooms.forEach { room -> rooms.forEach { room ->
...@@ -72,7 +64,7 @@ class RoomUiModelMapper( ...@@ -72,7 +64,7 @@ class RoomUiModelMapper(
private fun mapUser(user: User): RoomUiModel { private fun mapUser(user: User): RoomUiModel {
return with(user) { return with(user) {
val name = mapName(user.username!!, user.name, false) 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!!
...@@ -88,41 +80,56 @@ class RoomUiModelMapper( ...@@ -88,41 +80,56 @@ class RoomUiModelMapper(
} }
} }
private fun mapRoom(room: Room, showLastMessage:Boolean = true): RoomUiModel { private fun mapRoom(room: Room, showLastMessage: Boolean = true): RoomUiModel {
return 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) { mapLastMessage(lastMessage?.sender?.id, lastMessage?.sender?.username, lastMessage = if (showLastMessage) {
mapLastMessage(
lastMessage?.sender?.id, lastMessage?.sender?.username,
lastMessage?.sender?.name, lastMessage?.message, lastMessage?.sender?.name, lastMessage?.message,
isDirectMessage = type is RoomType.DirectMessage)} else { null }, isDirectMessage = type is RoomType.DirectMessage
)
} else {
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 {
return 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, isUnread) val roomName = mapName(name, fullname)
val timestamp = mapDate(lastMessageTimestamp ?: updatedAt, isUnread) 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) { mapLastMessage(lastMessageUserId, chatRoom.lastMessageUserName, val lastMessage = if (showLastMessage) {
chatRoom.lastMessageUserFullName, lastMessageText, isUnread, mapLastMessage(
type is RoomType.DirectMessage) } else { null } lastMessageUserId,
chatRoom.lastMessageUserName,
chatRoom.lastMessageUserFullName,
lastMessageText,
type is RoomType.DirectMessage
)
} else {
null
}
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,
...@@ -132,6 +139,7 @@ class RoomUiModelMapper( ...@@ -132,6 +139,7 @@ class RoomUiModelMapper(
open = open, open = open,
date = timestamp, date = timestamp,
unread = unread, unread = unread,
mentions = hasMentions,
alert = isUnread, alert = isUnread,
lastMessage = lastMessageMarkdown, lastMessage = lastMessageMarkdown,
status = status, status = status,
...@@ -158,47 +166,37 @@ class RoomUiModelMapper( ...@@ -158,47 +166,37 @@ class RoomUiModelMapper(
} }
} }
private fun mapLastMessage(userId: String?, name: String?, fullName: String?, text: String?, private fun mapLastMessage(
unread: Boolean = false, userId: String?,
isDirectMessage: Boolean = false): CharSequence? { name: String?,
fullName: String?,
text: String?,
isDirectMessage: Boolean = false
): CharSequence? {
return if (!settings.showLastMessage()) { return if (!settings.showLastMessage()) {
null null
} else if (name != null && text != null) { } else if (name != null && text != null) {
val user = if (currentUser != null && currentUser!!.id == userId) { val user = if (currentUser != null && currentUser!!.id == userId) {
"${context.getString(R.string.msg_you)}: " "${context.getString(R.string.msg_you)}: "
} else { } else {
if (isDirectMessage) "" else "${mapName(name, fullName, unread)}: " if (isDirectMessage) "" else "${mapName(name, fullName)}: "
} }
SpannableStringBuilder().append(user).append(text)
val color = if (unread) messageUnreadColor else messageColor
SpannableStringBuilder()
.color(color) {
bold { append(user) }
append(text)
}
} else { } else {
context.getText(R.string.msg_no_messages_yet) context.getText(R.string.msg_no_messages_yet)
} }
} }
private fun mapName(name: String, fullName: String?, unread: Boolean): CharSequence { private fun mapName(name: String, fullName: String?): CharSequence {
val roomName = if (settings.useSpecialCharsOnRoom() || settings.useRealName()) { return if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
fullName ?: name fullName ?: name
} else { } else {
name name
} }
val color = if (unread) nameUnreadColor else nameColor
return SpannableStringBuilder()
.color(color) {
append(roomName)
}
} }
private fun mapUnread(unread: Long): String? { private fun mapUnread(unread: Long): String? {
return 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)
...@@ -206,12 +204,14 @@ class RoomUiModelMapper( ...@@ -206,12 +204,14 @@ class RoomUiModelMapper(
} }
} }
private fun mapDate(date: Long?, unread: Boolean): CharSequence? { private fun mapMentions(userMentions: Long?, groupMentions: Long?): Boolean {
return date?.localDateTime()?.date(context)?.let { if (userMentions != null && groupMentions != null) {
val color = if (unread) dateUnreadColor else dateColor if (userMentions > 0 || groupMentions > 0) {
SpannableStringBuilder().color(color) { return true
append(it)
} }
} }
return false
} }
private fun mapDate(date: Long?): CharSequence? = date?.localDateTime()?.date(context)
} }
...@@ -4,6 +4,7 @@ import android.content.res.Resources ...@@ -4,6 +4,7 @@ import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.View import android.view.View
import androidx.core.view.isGone import androidx.core.view.isGone
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
...@@ -11,19 +12,16 @@ import chat.rocket.common.model.RoomType ...@@ -11,19 +12,16 @@ 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.*
import kotlinx.android.synthetic.main.unread_messages_badge.view.* import kotlinx.android.synthetic.main.unread_messages_badge.view.*
import ru.noties.markwon.Markwon
class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit) : ViewHolder<RoomItemHolder>(itemView) {
class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit) :
ViewHolder<RoomItemHolder>(itemView) {
private val resources: Resources = itemView.resources private val resources: Resources = itemView.resources
private val channelUnread: Drawable = resources.getDrawable(R.drawable.ic_hashtag_black_12dp) private val channelIcon: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp)
private val channel: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp) private val groupIcon: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp)
private val groupUnread: Drawable = resources.getDrawable(R.drawable.ic_lock_black_12_dp) private val onlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp)
private val group: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp) private val awayIcon: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp)
private val online: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp) private val busyIcon: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp)
private val away: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp) private val offlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp)
private val busy: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp)
private val offline: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp)
override fun bindViews(data: RoomItemHolder) { override fun bindViews(data: RoomItemHolder) {
val room = data.data val room = data.data
...@@ -31,53 +29,59 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit ...@@ -31,53 +29,59 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit
image_avatar.setImageURI(room.avatar) image_avatar.setImageURI(room.avatar)
text_chat_name.text = room.name text_chat_name.text = room.name
if (room.status != null && room.type is RoomType.DirectMessage) {
image_chat_icon.setImageDrawable(getStatusDrawable(room.status))
} else {
image_chat_icon.setImageDrawable(getRoomDrawable(room.type))
}
if (room.lastMessage != null) { if (room.lastMessage != null) {
text_last_message.isVisible = true
text_last_message.text = room.lastMessage text_last_message.text = room.lastMessage
text_last_message.isVisible = true
} else { } else {
text_last_message.isGone = true text_last_message.isGone = true
} }
if (room.date != null) { if (room.date != null) {
text_last_message_date_time.isVisible = true text_timestamp.text = room.date
text_last_message_date_time.text = room.date text_timestamp.isVisible = true
} else { } else {
text_last_message_date_time.isGone = true text_timestamp.isInvisible = true
} }
if (room.unread != null) { if (room.alert) {
if (room.unread == null) text_total_unread_messages.text = "!"
if (room.unread != null) 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_timestamp.setTextAppearance(context, R.style.ChatList_Timestamp_Unread_TextView)
text_last_message.setTextAppearance(context, R.style.ChatList_LastMessage_Unread_TextView)
text_total_unread_messages.isVisible = true text_total_unread_messages.isVisible = true
text_total_unread_messages.text = room.unread
} else { } else {
text_total_unread_messages.isGone = true text_chat_name.setTextAppearance(context, R.style.ChatList_ChatName_TextView)
text_timestamp.setTextAppearance(context, R.style.ChatList_Timestamp_TextView)
text_last_message.setTextAppearance(context, R.style.ChatList_LastMessage_TextView)
text_total_unread_messages.isInvisible = true
} }
if (room.status != null && room.type is RoomType.DirectMessage) { setOnClickListener { listener(room) }
image_chat_icon.setImageDrawable(getStatusDrawable(room.status))
} else {
image_chat_icon.setImageDrawable(getRoomDrawable(room.type, room.alert))
}
setOnClickListener {
listener(room)
}
} }
} }
private fun getRoomDrawable(type: RoomType, alert: Boolean): Drawable? { private fun getRoomDrawable(type: RoomType): Drawable? {
return when(type) { return when (type) {
is RoomType.Channel -> if (alert) channelUnread else channel is RoomType.Channel -> channelIcon
is RoomType.PrivateGroup -> if (alert) groupUnread else group is RoomType.PrivateGroup -> groupIcon
else -> null else -> null
} }
} }
private fun getStatusDrawable(status: UserStatus): Drawable { private fun getStatusDrawable(status: UserStatus): Drawable {
return when(status) { return when (status) {
is UserStatus.Online -> online is UserStatus.Online -> onlineIcon
is UserStatus.Away -> away is UserStatus.Away -> awayIcon
is UserStatus.Busy -> busy is UserStatus.Busy -> busyIcon
else -> offline else -> offlineIcon
} }
} }
} }
\ No newline at end of file
...@@ -6,7 +6,8 @@ import chat.rocket.android.R ...@@ -6,7 +6,8 @@ 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.extensions.inflate import chat.rocket.android.util.extensions.inflate
class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : RecyclerView.Adapter<ViewHolder<*>>() { class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) :
RecyclerView.Adapter<ViewHolder<*>>() {
init { init {
setHasStableIds(true) setHasStableIds(true)
...@@ -40,16 +41,16 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : RecyclerView.A ...@@ -40,16 +41,16 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : RecyclerView.A
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
val item = values[position] val item = values[position]
return when(item) { return when (item) {
is HeaderItemHolder -> item.data.hashCode().toLong()
is RoomItemHolder -> item.data.id.hashCode().toLong() is RoomItemHolder -> item.data.id.hashCode().toLong()
is HeaderItemHolder -> item.data.hashCode().toLong()
is LoadingItemHolder -> "loading".hashCode().toLong() is LoadingItemHolder -> "loading".hashCode().toLong()
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 getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return 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
......
...@@ -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 mentions: Boolean = false,
val lastMessage: CharSequence? = null, val lastMessage: CharSequence? = null,
val status: UserStatus? = null, val status: UserStatus? = null,
val username: String? = null, val username: String? = null,
......
package chat.rocket.android.chatrooms.ui
import DateTimeHelper
import DrawableHelper
import android.content.Context
import android.graphics.Color
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import chat.rocket.android.R
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.checkIfMyself
import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.util.extensions.*
import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom
import com.facebook.drawee.view.SimpleDraweeView
import kotlinx.android.synthetic.main.item_chat.view.*
import kotlinx.android.synthetic.main.unread_messages_badge.view.*
class ChatRoomsAdapter(
private val context: Context,
private val settings: PublicSettings,
private val localRepository: LocalRepository,
private val listener: (ChatRoom) -> Unit
) : RecyclerView.Adapter<ChatRoomsAdapter.ViewHolder>() {
var dataSet: MutableList<ChatRoom> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(parent.inflate(R.layout.item_chat))
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(dataSet[position])
override fun getItemCount(): Int = dataSet.size
fun updateRooms(newRooms: List<ChatRoom>) {
dataSet.clear()
dataSet.addAll(newRooms)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(chatRoom: ChatRoom) = with(itemView) {
bindAvatar(chatRoom, image_avatar)
bindName(chatRoom, text_chat_name)
bindIcon(chatRoom, image_chat_icon)
if (settings.showLastMessage()) {
text_last_message.isVisible = true
text_last_message_date_time.isVisible = true
bindLastMessageDateTime(chatRoom, text_last_message_date_time)
bindLastMessage(chatRoom, text_last_message)
} else {
text_last_message.isVisible = false
text_last_message_date_time.isVisible = false
}
bindUnreadMessages(chatRoom, text_total_unread_messages)
if (chatRoom.alert || chatRoom.unread > 0) {
text_chat_name.setTextColor(ContextCompat.getColor(context,
R.color.colorPrimaryText))
text_last_message_date_time.setTextColor(ContextCompat.getColor(context,
R.color.colorAccent))
text_last_message.setTextColor(ContextCompat.getColor(context,
android.R.color.primary_text_light))
} else {
text_chat_name.setTextColor(ContextCompat.getColor(context,
R.color.colorSecondaryText))
text_last_message_date_time.setTextColor(ContextCompat.getColor(context,
R.color.colorSecondaryText))
text_last_message.setTextColor(ContextCompat.getColor(context,
R.color.colorSecondaryText))
}
setOnClickListener { listener(chatRoom) }
}
private fun bindAvatar(chatRoom: ChatRoom, drawee: SimpleDraweeView) {
if (chatRoom.type is RoomType.DirectMessage) {
drawee.setImageURI(chatRoom.client.url.avatarUrl(chatRoom.name))
} else {
drawee.setImageURI(chatRoom.client.url.avatarUrl(chatRoom.name, true))
}
}
private fun bindIcon(chatRoom: ChatRoom, imageView: ImageView) {
val drawable = when (chatRoom.type) {
is RoomType.Channel -> DrawableHelper.getDrawableFromId(
R.drawable.ic_hashtag_black_12dp,
context
)
is RoomType.PrivateGroup -> DrawableHelper.getDrawableFromId(
R.drawable.ic_lock_black_12_dp,
context
)
is RoomType.DirectMessage -> DrawableHelper.getUserStatusDrawable(
chatRoom.status,
context
)
else -> null
}
drawable?.let {
val mutateDrawable = DrawableHelper.wrapDrawable(it).mutate()
if (chatRoom.type !is RoomType.DirectMessage) {
val color = when (chatRoom.alert || chatRoom.unread > 0) {
true -> R.color.colorPrimaryText
false -> R.color.colorSecondaryText
}
DrawableHelper.tintDrawable(mutateDrawable, context, color)
}
imageView.setImageDrawable(mutateDrawable)
}
}
private fun bindName(chatRoom: ChatRoom, textView: TextView) {
textView.textContent = chatRoomName(chatRoom)
}
private fun chatRoomName(chatRoom: ChatRoom): String {
return if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
chatRoom.fullName ?: chatRoom.name
} else {
chatRoom.name
}
}
private fun bindLastMessageDateTime(chatRoom: ChatRoom, textView: TextView) {
val lastMessage = chatRoom.lastMessage
if (lastMessage != null) {
val localDateTime = DateTimeHelper.getLocalDateTime(lastMessage.timestamp)
textView.content = DateTimeHelper.getDate(localDateTime, context)
} else {
textView.content = ""
}
}
private fun bindLastMessage(chatRoom: ChatRoom, textView: TextView) {
val lastMessage = chatRoom.lastMessage
val lastMessageSender = lastMessage?.sender
if (lastMessage != null && lastMessageSender != null) {
val message = lastMessage.message
val senderUsername = if (settings.useRealName()) {
lastMessageSender.name ?: lastMessageSender.username
} else {
lastMessageSender.username
}
when (senderUsername) {
chatRoom.name -> {
textView.content = message
}
else -> {
val user = if (localRepository.checkIfMyself(lastMessageSender.username!!)) {
"${context.getString(R.string.msg_you)}: "
} else {
"$senderUsername: "
}
val spannable = SpannableStringBuilder(user)
val len = spannable.length
spannable.setSpan(ForegroundColorSpan(Color.BLACK), 0, len - 1, 0)
spannable.append(message)
textView.content = spannable
}
}
} else {
textView.content = context.getText(R.string.msg_no_messages_yet)
}
}
private fun bindUnreadMessages(chatRoom: ChatRoom, textView: TextView) {
val totalUnreadMessage = chatRoom.unread
when {
totalUnreadMessage in 1..99 -> {
textView.textContent = totalUnreadMessage.toString()
textView.isVisible = true
}
totalUnreadMessage > 99 -> {
textView.textContent = context.getString(R.string.msg_more_than_ninety_nine_unread_messages)
textView.isVisible = true
}
else -> textView.isVisible = false
}
}
}
}
\ No newline at end of file
package chat.rocket.android.chatrooms.ui
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import java.util.*
class SimpleSectionedRecyclerViewAdapter(private val context: Context, private val sectionResourceId: Int, private val textResourceId: Int,
val baseAdapter: ChatRoomsAdapter) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var isValid = true
private val sectionsHeaders = SparseArray<Section>()
init {
baseAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
isValid = baseAdapter.itemCount > 0
notifyDataSetChanged()
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
isValid = baseAdapter.itemCount > 0
notifyItemRangeChanged(positionStart, itemCount)
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
isValid = baseAdapter.itemCount > 0
notifyItemRangeInserted(positionStart, itemCount)
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
isValid = baseAdapter.itemCount > 0
notifyItemRangeRemoved(positionStart, itemCount)
}
})
}
class SectionViewHolder(view: View, textResourceId: Int) : RecyclerView.ViewHolder(view) {
var title: TextView = view.findViewById<View>(textResourceId) as TextView
}
override fun onCreateViewHolder(parent: ViewGroup, typeView: Int): RecyclerView.ViewHolder {
return if (typeView == SECTION_TYPE) {
val view = LayoutInflater.from(context).inflate(sectionResourceId, parent, false)
SectionViewHolder(view, textResourceId)
} else {
baseAdapter.onCreateViewHolder(parent, typeView - 1)
}
}
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
if (isSectionHeaderPosition(position)) {
(viewHolder as SectionViewHolder).title.text = sectionsHeaders.get(position).title
} else {
baseAdapter.onBindViewHolder(viewHolder as ChatRoomsAdapter.ViewHolder, sectionedPositionToPosition(position))
}
}
override fun getItemViewType(position: Int): Int {
return if (isSectionHeaderPosition(position))
SECTION_TYPE
else
baseAdapter.getItemViewType(sectionedPositionToPosition(position)) + 1
}
class Section(internal var firstPosition: Int, var title: CharSequence) {
internal var sectionedPosition: Int = 0
}
fun setSections(sections: Array<Section>) {
sectionsHeaders.clear()
Arrays.sort(sections) { section1, section2 ->
when {
section1.firstPosition == section2.firstPosition -> 0
section1.firstPosition < section2.firstPosition -> -1
else -> 1
}
}
for ((offset, section) in sections.withIndex()) {
section.sectionedPosition = section.firstPosition + offset
sectionsHeaders.append(section.sectionedPosition, section)
}
notifyDataSetChanged()
}
fun clearSections(){
sectionsHeaders.clear()
notifyDataSetChanged()
}
fun positionToSectionedPosition(position: Int): Int {
var offset = 0
for (i in 0 until sectionsHeaders.size()) {
if (sectionsHeaders.valueAt(i).firstPosition > position) {
break
}
++offset
}
return position + offset
}
private fun sectionedPositionToPosition(sectionedPosition: Int): Int {
if (isSectionHeaderPosition(sectionedPosition)) {
return RecyclerView.NO_POSITION
}
var offset = 0
for (i in 0 until sectionsHeaders.size()) {
if (sectionsHeaders.valueAt(i).sectionedPosition > sectionedPosition) {
break
}
--offset
}
return sectionedPosition + offset
}
private fun isSectionHeaderPosition(position: Int): Boolean {
return sectionsHeaders.get(position) != null
}
override fun getItemId(position: Int): Long {
return when (isSectionHeaderPosition(position)) {
true -> (Integer.MAX_VALUE - sectionsHeaders.indexOfKey(position)).toLong()
false -> baseAdapter.getItemId(sectionedPositionToPosition(position))
}
}
override fun getItemCount(): Int {
return if (isValid) baseAdapter.itemCount + sectionsHeaders.size() else 0
}
companion object {
private const val SECTION_TYPE = 0
}
}
...@@ -38,6 +38,8 @@ import chat.rocket.android.server.ui.ChangeServerActivity ...@@ -38,6 +38,8 @@ import chat.rocket.android.server.ui.ChangeServerActivity
import chat.rocket.android.settings.di.SettingsFragmentProvider import chat.rocket.android.settings.di.SettingsFragmentProvider
import chat.rocket.android.settings.password.di.PasswordFragmentProvider import chat.rocket.android.settings.password.di.PasswordFragmentProvider
import chat.rocket.android.settings.password.ui.PasswordActivity import chat.rocket.android.settings.password.ui.PasswordActivity
import chat.rocket.android.userdetails.di.UserDetailsModule
import chat.rocket.android.userdetails.ui.UserDetailsActivity
import chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider import chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
...@@ -46,16 +48,16 @@ import dagger.android.ContributesAndroidInjector ...@@ -46,16 +48,16 @@ import dagger.android.ContributesAndroidInjector
abstract class ActivityBuilder { abstract class ActivityBuilder {
@PerActivity @PerActivity
@ContributesAndroidInjector( @ContributesAndroidInjector(
modules = [AuthenticationModule::class, modules = [AuthenticationModule::class,
OnBoardingFragmentProvider::class, OnBoardingFragmentProvider::class,
ServerFragmentProvider::class, ServerFragmentProvider::class,
LoginOptionsFragmentProvider::class, LoginOptionsFragmentProvider::class,
LoginFragmentProvider::class, LoginFragmentProvider::class,
RegisterUsernameFragmentProvider::class, RegisterUsernameFragmentProvider::class,
ResetPasswordFragmentProvider::class, ResetPasswordFragmentProvider::class,
SignupFragmentProvider::class, SignupFragmentProvider::class,
TwoFAFragmentProvider::class TwoFAFragmentProvider::class
] ]
) )
abstract fun bindAuthenticationActivity(): AuthenticationActivity abstract fun bindAuthenticationActivity(): AuthenticationActivity
...@@ -108,6 +110,11 @@ abstract class ActivityBuilder { ...@@ -108,6 +110,11 @@ abstract class ActivityBuilder {
@ContributesAndroidInjector(modules = [MessageInfoFragmentProvider::class]) @ContributesAndroidInjector(modules = [MessageInfoFragmentProvider::class])
abstract fun bindMessageInfoActiviy(): MessageInfoActivity abstract fun bindMessageInfoActiviy(): MessageInfoActivity
@PerActivity
@ContributesAndroidInjector(modules = [DrawModule::class]) @ContributesAndroidInjector(modules = [DrawModule::class])
abstract fun bindDrawingActivity(): DrawingActivity abstract fun bindDrawingActivity(): DrawingActivity
@PerActivity
@ContributesAndroidInjector(modules = [UserDetailsModule::class])
abstract fun bindUserDetailsActivity(): UserDetailsActivity
} }
...@@ -29,7 +29,7 @@ abstract class UserDao : BaseDao<UserEntity> { ...@@ -29,7 +29,7 @@ abstract class UserDao : BaseDao<UserEntity> {
abstract fun findUser(id: String): String? abstract fun findUser(id: String): String?
@Query("SELECT * FROM users WHERE ID = :id") @Query("SELECT * FROM users WHERE ID = :id")
abstract fun getUser(id:String): UserEntity? abstract fun getUser(id: String): UserEntity?
@Transaction @Transaction
open fun upsert(user: BaseUserEntity) { open fun upsert(user: BaseUserEntity) {
......
...@@ -47,4 +47,4 @@ class MembersAdapter(private val listener: (MemberUiModel) -> Unit) : ...@@ -47,4 +47,4 @@ class MembersAdapter(private val listener: (MemberUiModel) -> Unit) :
setOnClickListener { listener(memberUiModel) } setOnClickListener { listener(memberUiModel) }
} }
} }
} }
\ No newline at end of file
package chat.rocket.android.members.presentation package chat.rocket.android.members.presentation
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.members.ui.TAG_MEMBER_BOTTOM_SHEET_FRAGMENT import chat.rocket.android.userdetails.ui.userDetailsIntent
import chat.rocket.android.members.ui.newInstance
class MembersNavigator(internal val activity: ChatDetailsActivity) { class MembersNavigator(internal val activity: ChatDetailsActivity) {
fun toMemberDetails(avatarUri: String, realName: String, username: String, email: String, utcOffset: String) { fun toMemberDetails(userId: String) {
activity.apply { activity.apply {
newInstance(avatarUri, realName, username, email, utcOffset) startActivity(this.userDetailsIntent(userId, ""))
.show(supportFragmentManager, TAG_MEMBER_BOTTOM_SHEET_FRAGMENT)
} }
} }
} }
...@@ -59,12 +59,6 @@ class MembersPresenter @Inject constructor( ...@@ -59,12 +59,6 @@ class MembersPresenter @Inject constructor(
} }
fun toMemberDetails(memberUiModel: MemberUiModel) { fun toMemberDetails(memberUiModel: MemberUiModel) {
navigator.toMemberDetails( navigator.toMemberDetails(memberUiModel.userId)
memberUiModel.avatarUri.toString(),
memberUiModel.realName.toString(),
"@${memberUiModel.username}",
memberUiModel.email ?: "",
memberUiModel.utcOffset.toString()
)
} }
} }
\ No newline at end of file
...@@ -11,6 +11,7 @@ class MemberUiModel( ...@@ -11,6 +11,7 @@ class MemberUiModel(
private val settings: Map<String, Value<Any>>, private val settings: Map<String, Value<Any>>,
private val baseUrl: String? private val baseUrl: String?
) { ) {
val userId: String = member.id
val avatarUri: String? val avatarUri: String?
val displayName: String val displayName: String
val realName: String? val realName: String?
...@@ -52,4 +53,4 @@ class MemberUiModel( ...@@ -52,4 +53,4 @@ class MemberUiModel(
private fun getUserUtcOffset(): Float? = member.utcOffset private fun getUserUtcOffset(): Float? = member.utcOffset
private fun getUserStatus(): UserStatus? = member.status private fun getUserStatus(): UserStatus? = member.status
} }
\ No newline at end of file
...@@ -7,11 +7,14 @@ import chat.rocket.common.model.User ...@@ -7,11 +7,14 @@ import chat.rocket.common.model.User
import chat.rocket.core.model.Value import chat.rocket.core.model.Value
import javax.inject.Inject import javax.inject.Inject
class MemberUiModelMapper @Inject constructor(serverInteractor: GetCurrentServerInteractor, getSettingsInteractor: GetSettingsInteractor) { class MemberUiModelMapper @Inject constructor(
serverInteractor: GetCurrentServerInteractor,
getSettingsInteractor: GetSettingsInteractor
) {
private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!) private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!)
private val baseUrl = settings.baseUrl() private val baseUrl = settings.baseUrl()
fun mapToUiModelList(memberList: List<User>): List<MemberUiModel> { fun mapToUiModelList(memberList: List<User>): List<MemberUiModel> {
return memberList.map { MemberUiModel(it, settings, baseUrl) } return memberList.map { MemberUiModel(it, settings, baseUrl) }
} }
} }
\ No newline at end of file
...@@ -35,10 +35,6 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback { ...@@ -35,10 +35,6 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
private var actionMode: ActionMode? = null private var actionMode: ActionMode? = null
private val disposables = CompositeDisposable() private val disposables = CompositeDisposable()
companion object {
fun newInstance() = PasswordFragment()
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -143,4 +139,8 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback { ...@@ -143,4 +139,8 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
actionMode = (activity as PasswordActivity).startSupportActionMode(this) actionMode = (activity as PasswordActivity).startSupportActionMode(this)
} }
} }
}
\ No newline at end of file companion object {
fun newInstance() = PasswordFragment()
}
}
package chat.rocket.android.userdetails.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.userdetails.presentation.UserDetailsView
import chat.rocket.android.userdetails.ui.UserDetailsActivity
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
@Module
class UserDetailsModule {
@Provides
@PerActivity
fun provideJob() = Job()
@Provides
@PerActivity
fun provideUserDetailsView(activity: UserDetailsActivity): UserDetailsView = activity
@Provides
@PerActivity
fun provideLifecycleOwner(activity: UserDetailsActivity): LifecycleOwner = activity
@Provides
@PerActivity
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
}
package chat.rocket.android.userdetails.presentation
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.domain.GetConnectingServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.retryIO
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.model.userStatusOf
import chat.rocket.core.internal.rest.createDirectMessage
import chat.rocket.core.model.ChatRoom
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.withContext
import timber.log.Timber
import javax.inject.Inject
class UserDetailsPresenter @Inject constructor(
private val view: UserDetailsView,
private val dbManager: DatabaseManager,
private val strategy: CancelStrategy,
serverInteractor: GetConnectingServerInteractor,
factory: ConnectionManagerFactory
) {
private var currentServer = serverInteractor.get()!!
private val manager = factory.create(currentServer)
private val client = manager.client
fun loadUserDetails(userId: String) {
launchUI(strategy) {
try {
val user = withContext(CommonPool) {
dbManager.userDao().getUser(id = userId)
}
user?.let { u ->
val openedChatRooms = chatRoomByName(name = u.name)
val avatarUrl = u.username?.let { currentServer.avatarUrl(avatar = it) }
val chatRoom: ChatRoom? = if (openedChatRooms.isEmpty()) {
ChatRoom(
id = "",
type = roomTypeOf(RoomType.DIRECT_MESSAGE),
name = u.username ?: u.name.orEmpty(),
fullName = u.name,
favorite = false,
open = false,
alert = false,
status = userStatusOf(u.status),
client = client,
broadcast = false,
archived = false,
default = false,
description = null,
groupMentions = null,
userMentions = null,
lastMessage = null,
lastSeen = null,
topic = null,
announcement = null,
roles = null,
unread = 0,
readonly = false,
muted = null,
subscriptionId = "",
timestamp = null,
updatedAt = null,
user = null
)
} else openedChatRooms.firstOrNull()
view.showUserDetails(
avatarUrl = avatarUrl,
username = u.username,
name = u.name,
utcOffset = u.utcOffset,
status = u.status,
chatRoom = chatRoom
)
}
} catch (ex: Exception) {
Timber.e(ex)
}
}
}
fun createDirectMessage(id: String) = launchUI(strategy) {
try {
val result = retryIO("createDirectMessage($id") {
client.createDirectMessage(username = id)
}
val userEntity = withContext(CommonPool) {
dbManager.userDao().getUser(id = id)
}
if (userEntity != null) {
view.toDirectMessage(
chatRoom = ChatRoom(
id = result.id,
type = roomTypeOf(RoomType.DIRECT_MESSAGE),
name = userEntity.username ?: userEntity.name.orEmpty(),
fullName = userEntity.name,
favorite = false,
open = false,
alert = false,
status = userStatusOf(userEntity.status),
client = client,
broadcast = false,
archived = false,
default = false,
description = null,
groupMentions = null,
userMentions = null,
lastMessage = null,
lastSeen = null,
topic = null,
announcement = null,
roles = null,
unread = 0,
readonly = false,
muted = null,
subscriptionId = "",
timestamp = null,
updatedAt = result.updatedAt,
user = null
)
)
}
} catch (ex: Exception) {
Timber.e(ex)
view.onOpenDirectMessageError()
}
}
private suspend fun chatRoomByName(name: String? = null): List<ChatRoom> = withContext(CommonPool) {
return@withContext dbManager.chatRoomDao().getAllSync().filter {
if (name == null) {
return@filter true
}
it.chatRoom.name == name || it.chatRoom.fullname == name
}.map {
with(it.chatRoom) {
ChatRoom(
id = id,
subscriptionId = subscriptionId,
type = roomTypeOf(type),
unread = unread,
broadcast = broadcast ?: false,
alert = alert,
fullName = fullname,
name = name ?: "",
favorite = favorite ?: false,
default = isDefault ?: false,
readonly = readonly,
open = open,
lastMessage = null,
archived = false,
status = null,
user = null,
userMentions = userMentions,
client = client,
announcement = null,
description = null,
groupMentions = groupMentions,
roles = null,
topic = null,
lastSeen = this.lastSeen,
timestamp = timestamp,
updatedAt = updatedAt
)
}
}
}
}
package chat.rocket.android.userdetails.presentation
import chat.rocket.core.model.ChatRoom
interface UserDetailsView {
fun showUserDetails(avatarUrl: String?, username: String?, name: String?, utcOffset: Float?, status: String, chatRoom: ChatRoom?)
fun toDirectMessage(chatRoom: ChatRoom)
fun onOpenDirectMessageError()
}
package chat.rocket.android.userdetails.ui
import android.content.Context
import android.content.Intent
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import blurred
import chat.rocket.android.R
import chat.rocket.android.chatroom.ui.chatRoomIntent
import chat.rocket.android.emoji.internal.GlideApp
import chat.rocket.android.userdetails.presentation.UserDetailsPresenter
import chat.rocket.android.userdetails.presentation.UserDetailsView
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extension.orFalse
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.retryIO
import chat.rocket.common.model.roomTypeOf
import chat.rocket.core.internal.rest.createDirectMessage
import chat.rocket.core.model.ChatRoom
import chat.rocket.core.model.userId
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.CenterInside
import com.bumptech.glide.load.resource.bitmap.FitCenter
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.google.android.material.snackbar.Snackbar
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.activity_user_details.*
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext
import org.threeten.bp.OffsetDateTime
import org.threeten.bp.ZoneId
import org.threeten.bp.ZoneOffset
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.format.DateTimeFormatter
import timber.log.Timber
import javax.inject.Inject
import kotlin.math.roundToLong
fun Context.userDetailsIntent(userId: String, subscriptionId: String): Intent {
return Intent(this, UserDetailsActivity::class.java).apply {
putExtra(EXTRA_USER_ID, userId)
putExtra(EXTRA_SUBSCRIPTION_ID, subscriptionId)
}
}
const val EXTRA_USER_ID = "EXTRA_USER_ID"
const val EXTRA_SUBSCRIPTION_ID = "EXTRA_USERNAME"
class UserDetailsActivity : AppCompatActivity(), UserDetailsView, HasSupportFragmentInjector {
@Inject
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
@Inject
lateinit var presenter: UserDetailsPresenter
private lateinit var subscriptionId: String
private lateinit var userId: String
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user_details)
setupToolbar()
userId = intent.getStringExtra(EXTRA_USER_ID)
subscriptionId = intent.getStringExtra(EXTRA_SUBSCRIPTION_ID)
showLoadingView(true)
presenter.loadUserDetails(userId = userId)
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> = fragmentDispatchingAndroidInjector
private fun setupToolbar() {
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false)
toolbar.setNavigationOnClickListener { finish() }
}
override fun showUserDetails(
avatarUrl: String?,
username: String?,
name: String?,
utcOffset: Float?,
status: String,
chatRoom: ChatRoom?
) {
text_view_name.text = name
text_view_username.text = username
text_view_status.text = status.capitalize()
try {
launch(UI) {
val image = withContext(CommonPool) {
try {
val requestOptions = RequestOptions()
.priority(Priority.IMMEDIATE)
.transforms(CenterInside(), FitCenter())
return@withContext GlideApp.with(this@UserDetailsActivity)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.load(avatarUrl)
.apply(requestOptions)
.submit()
.get()
} catch (ex: Exception) {
Timber.e(ex)
return@withContext null
} finally {
showLoadingView(false)
}
}
image?.let {
val blurredBitmap = image.blurred(context = this@UserDetailsActivity,
newWidth = toolbar.measuredWidth, newHeight = toolbar.measuredHeight)
toolbar.background = BitmapDrawable(resources, blurredBitmap)
GlideApp.with(this@UserDetailsActivity)
.asBitmap()
.transforms(RoundedCorners(25), CenterCrop())
.load(image)
.into(image_view_avatar)
}
}
utcOffset?.let {
val offsetLong = it.roundToLong()
val offset = if (it > 0) "+$offsetLong" else offsetLong.toString()
val formatter = DateTimeFormatter.ofPattern("'(GMT$offset)' hh:mm a")
val zoneId = ZoneId.systemDefault()
val timeNow = OffsetDateTime.now(ZoneOffset.UTC).plusHours(offsetLong).toLocalDateTime()
text_view_tz.text = formatter.format(ZonedDateTime.of(timeNow, zoneId))
}
text_view_message.setOnClickListener {
if (chatRoom == null) {
presenter.createDirectMessage(id = userId)
} else {
toDirectMessage(chatRoom)
}
}
image_view_message.setOnClickListener {
if (chatRoom == null) {
presenter.createDirectMessage(id = userId)
} else {
toDirectMessage(chatRoom)
}
}
} catch (ex: Exception) {
Timber.e(ex)
}
}
private fun showLoadingView(show: Boolean) {
runOnUiThread {
group_user_details.isVisible = !show
view_loading.isVisible = show
}
}
override fun onOpenDirectMessageError() {
Snackbar.make(root_layout, R.string.error_opening_dm, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.retry) {
presenter.createDirectMessage(userId)
}.show()
}
override fun toDirectMessage(chatRoom: ChatRoom) {
finish()
if (chatRoom.subscriptionId.isEmpty() || chatRoom.subscriptionId != subscriptionId) {
startActivity(
chatRoomIntent(
chatRoomId = chatRoom.id,
chatRoomName = chatRoom.name,
chatRoomType = chatRoom.type.toString(),
isReadOnly = chatRoom.readonly.orFalse(),
chatRoomLastSeen = chatRoom.lastSeen ?: 0,
isSubscribed = chatRoom.open,
isCreator = false,
isFavorite = chatRoom.favorite
)
)
}
}
}
import android.content.Context
import android.graphics.Bitmap
import android.renderscript.Allocation
import android.renderscript.Element
import android.renderscript.RenderScript
import android.renderscript.ScriptIntrinsicBlur
fun Bitmap.blurred(context: Context, intensity: Float = 25f, newWidth: Int = -1, newHeight: Int = -1): Bitmap {
if (intensity <= 0 || intensity > 25) {
throw IllegalStateException("Intensity out of range (0 < intensity <= 25).")
}
val nonScaledBitmap = copy(config, true)
val bitmap = if (newWidth > 0 && newHeight > 0) {
val height = nonScaledBitmap.height
val width = nonScaledBitmap.width
val aspectRadio = width / height
val adjustedWidth = newHeight * aspectRadio
val adjustedHeight = newWidth * height / width
val scaledBitmap = Bitmap.createScaledBitmap(nonScaledBitmap, adjustedWidth, adjustedHeight, false)
Bitmap.createBitmap(scaledBitmap, 0, 0, adjustedWidth, newHeight)
} else nonScaledBitmap
val rs = RenderScript.create(context)
val input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT)
val output = Allocation.createTyped(rs, input.type)
val script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
script.setRadius(intensity)
script.setInput(input)
script.forEach(output)
output.copyTo(bitmap)
return bitmap
}
...@@ -118,4 +118,4 @@ fun Menu.toList(): List<MenuItem> { ...@@ -118,4 +118,4 @@ fun Menu.toList(): List<MenuItem> {
val menuItems = ArrayList<MenuItem>(this.size()) val menuItems = ArrayList<MenuItem>(this.size())
(0 until this.size()).mapTo(menuItems) { this.getItem(it) } (0 until this.size()).mapTo(menuItems) { this.getItem(it) }
return menuItems return menuItems
} }
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<solid android:color="@android:color/white" />
<corners android:radius="25px" />
</shape>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="@color/actionMenuColor"
android:pathData="M10.11,16.546h-0.183c-4.329,0 -7.47,-2.753 -7.47,-6.546 0,-3.61 2.942,-6.547 6.56,-6.547 3.616,0 6.56,2.937 6.56,6.547 0,0.59 -0.276,1.18 -0.567,1.803 -0.1,0.218 -0.2,0.433 -0.278,0.618 -0.756,1.626 0.731,2.41 1.364,2.743 0.098,0.051 0.224,0.117 0.326,0.178 -0.416,0.478 -1.814,1.22 -6.312,1.204m6.666,-2.667c-0.895,-0.473 -0.852,-0.567 -0.71,-0.875 0.081,-0.193 0.172,-0.389 0.264,-0.587 0.33,-0.705 0.703,-1.505 0.703,-2.417 0,-4.412 -3.597,-8 -8.017,-8S1,5.588 1,10c0,4.635 3.755,8 8.927,8h0.382c2.857,0 6.632,-0.256 7.565,-2.237 0.493,-1.046 -0.58,-1.612 -1.098,-1.884" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportHeight="12"
android:viewportWidth="12">
<path
android:fillColor="#DE000000"
android:fillType="evenOdd"
android:pathData="M2.4,0h1.2v12h-1.2z" />
<path
android:fillColor="#DE000000"
android:fillType="evenOdd"
android:pathData="M0,2.4h12v1.2h-12z" />
<path
android:fillColor="#DE000000"
android:fillType="evenOdd"
android:pathData="M0,8.4h12v1.2h-12z" />
<path
android:fillColor="#DE000000"
android:fillType="evenOdd"
android:pathData="M8.4,0h1.2v12h-1.2z" />
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="#1d74f5"
android:fillType="evenOdd"
android:pathData="M10.11,16.546h-0.183c-4.329,0 -7.47,-2.753 -7.47,-6.546 0,-3.61 2.942,-6.547 6.56,-6.547 3.616,0 6.56,2.937 6.56,6.547 0,0.59 -0.276,1.18 -0.567,1.803 -0.1,0.218 -0.2,0.433 -0.278,0.618 -0.756,1.626 0.731,2.41 1.364,2.743 0.098,0.051 0.224,0.117 0.326,0.178 -0.416,0.478 -1.814,1.22 -6.312,1.204m6.666,-2.667c-0.895,-0.473 -0.852,-0.567 -0.71,-0.875 0.081,-0.193 0.172,-0.389 0.264,-0.587 0.33,-0.705 0.703,-1.505 0.703,-2.417 0,-4.412 -3.597,-8 -8.017,-8S1,5.588 1,10c0,4.635 3.755,8 8.927,8h0.382c2.857,0 6.632,-0.256 7.565,-2.237 0.493,-1.046 -0.58,-1.612 -1.098,-1.884" />
</vector>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"> android:shape="rectangle">
<solid android:color="@color/colorAccent" /> <solid android:color="@color/colorAccent" />
<corners android:radius="4dp" />
</shape> </shape>
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
android:orientation="vertical" android:orientation="vertical"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:context=".settings.password.ui.PasswordActivity"> tools:context=".settings.password.ui.PasswordActivity">
<include <include
android:id="@+id/layout_app_bar" android:id="@+id/layout_app_bar"
layout="@layout/app_bar_password" /> layout="@layout/app_bar_password" />
<FrameLayout <FrameLayout
android:id="@+id/fragment_container" android:id="@+id/fragment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
</LinearLayout> </LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:fitsSystemWindows="true">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/view_loading"
style="@style/Authentication.AVLoadingIndicatorView"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<ImageView
android:id="@+id/image_view_message"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_username"
app:srcCompat="@drawable/ic_message_24dp" />
<TextView
android:id="@+id/text_view_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message"
android:textColor="#1d74f5"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="@+id/image_view_message"
app:layout_constraintStart_toStartOf="@+id/image_view_message"
app:layout_constraintTop_toBottomOf="@+id/image_view_message" />
<TextView
android:id="@+id/text_view_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:fontFamily="sans-serif-medium"
android:textColor="@android:color/black"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Karem Flusser" />
<TextView
android:id="@+id/text_view_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textColor="@color/darkGray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_name"
tools:text="karem.flusser" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:text="@string/status"
android:textColor="@color/darkGray"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_message" />
<TextView
android:id="@+id/text_view_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textColor="@android:color/black"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3"
tools:text="Online" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/timezone"
android:textColor="@color/darkGray"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_status" />
<TextView
android:id="@+id/text_view_tz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textColor="@android:color/black"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:text="(UTC-2) 11:08 AM" />
<androidx.constraintlayout.widget.Group
android:id="@+id/group_user_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="text_view_tz,textView,text_view_status,text_view_message,textView3,text_view_name,text_view_username,image_view_message" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
app:elevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="@android:color/white"
app:expandedTitleGravity="top"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="?actionBarSize"
app:elevation="0dp"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:navigationIcon="?android:attr/homeAsUpIndicator"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<ImageView
android:id="@+id/image_view_avatar"
android:layout_width="98dp"
android:layout_height="98dp"
android:layout_gravity="center_horizontal"
android:layout_marginStart="16dp"
android:layout_marginTop="?actionBarSize"
android:layout_marginEnd="16dp"
android:background="@drawable/bg_round_bounds_white"
tools:srcCompat="@tools:sample/avatars[6]" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--<androidx.core.widget.NestedScrollView 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="wrap_content"-->
<!--android:fillViewport="true">-->
<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="wrap_content"
android:paddingBottom="16dp">
<!--<com.google.android.material.appbar.AppBarLayout-->
<!--android:id="@+id/appBarLayout"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content"-->
<!--android:background="@color/colorPrimary"-->
<!--android:theme="@style/Theme.AppCompat.Light.NoActionBar">-->
<!--<androidx.appcompat.widget.Toolbar-->
<!--android:id="@+id/toolbar"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="?attr/actionBarSize"-->
<!--app:layout_scrollFlags="scroll|enterAlways"-->
<!--app:navigationIcon="?android:attr/homeAsUpIndicator"-->
<!--app:popupTheme="@style/ThemeOverlay.AppCompat.Light"-->
<!--app:theme="@style/ActionModeStyle">-->
<!--<RelativeLayout-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content">-->
<!--<TextView-->
<!--android:id="@+id/text_change_password"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_alignParentStart="true"-->
<!--android:ellipsize="end"-->
<!--android:maxLines="1"-->
<!--android:text="@string/action_msg_report"-->
<!--android:textColor="@color/colorWhite"-->
<!--android:textSize="18sp"-->
<!--android:textStyle="bold" />-->
<!--</RelativeLayout>-->
<!--</androidx.appcompat.widget.Toolbar>-->
<!--</com.google.android.material.appbar.AppBarLayout>-->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="24dp" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="24dp" />
<!--<TextView-->
<!--android:id="@+id/text_view_report_label"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:text="Description"-->
<!--android:textColor="@color/darkGray"-->
<!--app:layout_constraintStart_toStartOf="@+id/guideline_start"-->
<!--app:layout_constraintTop_toTopOf="parent" />-->
<!--<TextView-->
<!--android:id="@+id/text_view_required"-->
<!--android:layout_width="0dp"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_marginStart="8dp"-->
<!--android:text="(required)"-->
<!--android:textColor="@color/darkGray"-->
<!--android:textSize="14sp"-->
<!--app:layout_constraintEnd_toEndOf="@+id/guideline_end"-->
<!--app:layout_constraintStart_toEndOf="@id/text_view_report_label"-->
<!--app:layout_constraintTop_toTopOf="parent" />-->
<EditText
android:id="@+id/edit_text_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:inputType="textCapSentences|textMultiLine"
android:maxLines="4"
android:overScrollMode="always"
android:scrollbarStyle="insideInset"
android:scrollbars="vertical"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="@+id/guideline_end"
app:layout_constraintStart_toStartOf="@+id/guideline_start"
app:layout_constraintTop_toTopOf="parent"
tools:text="Jot something untoward..." />
<TextView
android:id="@+id/text_view_error"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/required"
android:textColor="@color/colorRed"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="@+id/guideline_end"
app:layout_constraintStart_toStartOf="@+id/guideline_start"
app:layout_constraintTop_toBottomOf="@+id/edit_text_description"
tools:visibility="visible" />
<Button
android:id="@+id/button_send_report"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/rounded_color_accent"
android:fontFamily="sans-serif-medium"
android:text="@string/submit"
android:textColor="@android:color/white"
app:layout_constraintEnd_toEndOf="@+id/guideline_end"
app:layout_constraintStart_toStartOf="@+id/guideline_start"
app:layout_constraintTop_toBottomOf="@id/text_view_error" />1
</androidx.constraintlayout.widget.ConstraintLayout>
<!--</androidx.core.widget.NestedScrollView>-->
...@@ -5,19 +5,19 @@ ...@@ -5,19 +5,19 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:paddingBottom="@dimen/chat_item_top_and_bottom_padding"
android:paddingEnd="@dimen/screen_edge_left_and_right_padding"
android:paddingStart="@dimen/screen_edge_left_and_right_padding" android:paddingStart="@dimen/screen_edge_left_and_right_padding"
android:paddingTop="@dimen/chat_item_top_and_bottom_padding"> android:paddingTop="@dimen/chat_item_top_and_bottom_padding"
android:paddingEnd="@dimen/screen_edge_left_and_right_padding"
android:paddingBottom="@dimen/chat_item_top_and_bottom_padding">
<com.facebook.drawee.view.SimpleDraweeView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image_avatar" android:id="@+id/image_avatar"
android:layout_width="40dp" android:layout_width="48dp"
android:layout_height="40dp" android:layout_height="48dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:roundedCornerRadius="3dp" /> app:roundedCornerRadius="4dp" />
<ImageView <ImageView
android:id="@+id/image_chat_icon" android:id="@+id/image_chat_icon"
...@@ -27,65 +27,50 @@ ...@@ -27,65 +27,50 @@
app:layout_constraintBottom_toBottomOf="@+id/text_chat_name" app:layout_constraintBottom_toBottomOf="@+id/text_chat_name"
app:layout_constraintStart_toEndOf="@+id/image_avatar" app:layout_constraintStart_toEndOf="@+id/image_avatar"
app:layout_constraintTop_toTopOf="@+id/text_chat_name" app:layout_constraintTop_toTopOf="@+id/text_chat_name"
tools:src="@drawable/ic_hashtag_unread_12dp" /> tools:src="@drawable/ic_hashtag_12dp" />
<TextView
android:id="@+id/text_last_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginTop="2dp"
android:layout_weight="0.8"
android:ellipsize="end"
android:maxLines="2"
android:textDirection="locale"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/image_chat_icon"
app:layout_constraintTop_toBottomOf="@+id/text_chat_name"
tools:text="Filipe de Lima Brito: Type something that is very big and need at least to lines, or maybe even more" />
<TextView <TextView
android:id="@+id/text_chat_name" android:id="@+id/text_chat_name"
style="@style/ChatRoom.Name.TextView" style="@style/ChatList.ChatName.TextView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/text_view_drawable_padding" android:layout_marginStart="@dimen/text_view_drawable_padding"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textDirection="locale" android:textDirection="locale"
android:textColor="@color/colorSecondaryText" app:layout_constraintEnd_toStartOf="@+id/text_timestamp"
app:layout_constraintBottom_toTopOf="@+id/text_last_message"
app:layout_constraintEnd_toStartOf="@+id/text_last_message_date_time"
app:layout_constraintStart_toEndOf="@+id/image_chat_icon" app:layout_constraintStart_toEndOf="@+id/image_chat_icon"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="general" /> tools:text="Margaret Hanson" />
<TextView <TextView
android:id="@+id/text_last_message_date_time" android:id="@+id/text_timestamp"
style="@style/Timestamp.TextView" style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
android:gravity="center" android:textDirection="locale"
android:layout_marginEnd="8dp" app:layout_constraintBaseline_toBaselineOf="@+id/text_chat_name"
app:layout_constraintBottom_toBottomOf="@+id/layout_unread_messages_badge" app:layout_constraintEnd_toEndOf="parent"
tools:text="11:45 AM" />
<TextView
android:id="@+id/text_last_message"
style="@style/ChatList.LastMessage.TextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:ellipsize="end" android:layout_marginEnd="12dp"
android:maxLines="2"
android:textDirection="locale" android:textDirection="locale"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge" app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge"
app:layout_constraintTop_toTopOf="@+id/text_chat_name" app:layout_constraintStart_toStartOf="@+id/image_chat_icon"
tools:text="11:45 AM" /> app:layout_constraintTop_toBottomOf="@+id/text_chat_name"
tools:text="Filipe de Lima Brito: Type something that is very big and need at least to lines, or maybe even more" />
<include <include
android:id="@+id/layout_unread_messages_badge" android:id="@+id/layout_unread_messages_badge"
layout="@layout/unread_messages_badge" layout="@layout/unread_messages_badge"
android:layout_width="18dp" android:layout_width="21dp"
android:layout_height="18dp" android:layout_height="21dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/text_chat_name" /> app:layout_constraintTop_toTopOf="@+id/text_last_message" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -92,11 +92,11 @@ ...@@ -92,11 +92,11 @@
android:id="@+id/message_header" android:id="@+id/message_header"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@+id/layout_avatar" app:layout_constraintLeft_toRightOf="@+id/layout_avatar"
app:layout_constraintStart_toEndOf="@+id/layout_avatar" app:layout_constraintStart_toEndOf="@+id/layout_avatar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/day_marker_layout"> app:layout_constraintTop_toBottomOf="@+id/day_marker_layout">
<TextView <TextView
...@@ -104,13 +104,13 @@ ...@@ -104,13 +104,13 @@
style="@style/Sender.Name.TextView" style="@style/Sender.Name.TextView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_weight="1"
tools:text="User Name with long name" /> tools:text="User Name with long name" />
<TextView <TextView
android:id="@+id/text_message_time" android:id="@+id/text_message_time"
style="@style/Timestamp.TextView" style="@style/ChatRoom.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="4dp" android:layout_marginStart="4dp"
......
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
<TextView <TextView
android:id="@+id/text_message_time" android:id="@+id/text_message_time"
style="@style/Timestamp.TextView" style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
<TextView <TextView
android:id="@+id/text_message_time" android:id="@+id/text_message_time"
style="@style/Timestamp.TextView" style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
......
...@@ -6,15 +6,12 @@ ...@@ -6,15 +6,12 @@
<TextView <TextView
android:id="@+id/text_total_unread_messages" android:id="@+id/text_total_unread_messages"
style="@style/TextAppearance.AppCompat.Caption" style="@style/ChatList.Badge.TextView"
android:layout_width="18dp" android:layout_width="21dp"
android:layout_height="18dp" android:layout_height="21dp"
android:background="@drawable/style_total_unread_messages" android:background="@drawable/style_total_unread_messages"
android:gravity="center"
android:textColor="@color/colorWhite"
android:textSize="10sp"
android:visibility="gone" android:visibility="gone"
tools:text="99+" tools:text="1"
tools:visibility="visible" /> tools:visibility="visible" />
</LinearLayout> </LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:app="http://schemas.android.com/apk/res-auto">
<item <item
android:id="@+id/action_message_info" android:id="@+id/action_message_info"
android:icon="@drawable/ic_action_message_info_outline_24dp" android:icon="@drawable/ic_action_message_info_outline_24dp"
android:title="@string/action_msg_info" /> android:title="@string/action_msg_info" />
<item <item
android:id="@+id/action_message_reply" android:id="@+id/action_message_reply"
android:icon="@drawable/ic_action_message_reply_24dp" android:icon="@drawable/ic_action_message_reply_24dp"
android:title="@string/action_msg_reply" /> android:title="@string/action_msg_reply" />
<item
android:id="@+id/action_message_edit"
android:icon="@drawable/ic_action_message_edit_24dp"
android:title="@string/action_msg_edit" />
<item
android:id="@+id/action_menu_msg_react"
android:icon="@drawable/ic_add_reaction"
android:title="@string/action_msg_add_reaction" />
<item <item
android:id="@+id/action_message_permalink" android:id="@+id/action_message_permalink"
...@@ -27,11 +34,6 @@ ...@@ -27,11 +34,6 @@
android:icon="@drawable/ic_action_message_copy_24dp" android:icon="@drawable/ic_action_message_copy_24dp"
android:title="@string/action_msg_copy" /> android:title="@string/action_msg_copy" />
<item
android:id="@+id/action_menu_msg_react"
android:icon="@drawable/ic_add_reaction"
android:title="@string/action_msg_add_reaction" />
<!--<item--> <!--<item-->
<!--android:id="@+id/action_menu_msg_share"--> <!--android:id="@+id/action_menu_msg_share"-->
<!--andrtextIconicon="@drawable/ic_share_black_24px"--> <!--andrtextIconicon="@drawable/ic_share_black_24px"-->
...@@ -48,9 +50,9 @@ ...@@ -48,9 +50,9 @@
android:title="@string/action_msg_pin" /> android:title="@string/action_msg_pin" />
<item <item
android:id="@+id/action_message_edit" android:id="@+id/action_message_report"
android:icon="@drawable/ic_action_message_edit_24dp" android:icon="@drawable/ic_action_message_report_24dp"
android:title="@string/action_msg_edit" /> android:title="@string/action_msg_report" />
<item <item
android:id="@+id/action_message_delete" android:id="@+id/action_message_delete"
......
...@@ -225,6 +225,8 @@ ...@@ -225,6 +225,8 @@
<string name="action_msg_add_reaction">Reaktion hinzufügen</string> <string name="action_msg_add_reaction">Reaktion hinzufügen</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Bearbeiten nicht erlaubt</string> <string name="permission_editing_not_allowed">Bearbeiten nicht erlaubt</string>
...@@ -329,6 +331,16 @@ ...@@ -329,6 +331,16 @@
<string name="notif_success_sending">Nachricht gesendet nach %1$s!</string> <string name="notif_success_sending">Nachricht gesendet nach %1$s!</string>
<string name="read_by">Gelesen von</string> <string name="read_by">Gelesen von</string>
<string name="message_information_title">Nachricht Information</string> <string name="message_information_title">Nachricht Information</string>
<!--TODO - Add proper translation--> <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">Room type changed to: %1$s by %2$s</string>
</resources> <!-- User Details -->
\ No newline at end of file <string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources>
...@@ -220,6 +220,8 @@ ...@@ -220,6 +220,8 @@
<string name="action_title_editing">Edición de mensaje</string> <string name="action_title_editing">Edición de mensaje</string>
<string name="action_msg_add_reaction">Añadir una reacción</string> <string name="action_msg_add_reaction">Añadir una reacción</string>
<string name="action_msg_copy_permalink">Copiar permalink</string> <string name="action_msg_copy_permalink">Copiar permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">La edición no és permitida</string> <string name="permission_editing_not_allowed">La edición no és permitida</string>
...@@ -330,6 +332,16 @@ ...@@ -330,6 +332,16 @@
<string name="msg_file_description">Descripción del archivo</string> <string name="msg_file_description">Descripción del archivo</string>
<string name="msg_send">Enviar</string> <string name="msg_send">Enviar</string>
<string name="msg_sent_attachment">Envió un archivo</string> <string name="msg_sent_attachment">Envió un archivo</string>
<!--TODO - Add proper translation--> <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">Room type changed to: %1$s by %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources> </resources>
...@@ -226,6 +226,8 @@ ...@@ -226,6 +226,8 @@
<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 --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</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>
...@@ -334,4 +336,15 @@ ...@@ -334,4 +336,15 @@
<string name="msg_sent_attachment">Envoyé un fichier</string> <string name="msg_sent_attachment">Envoyé un fichier</string>
<!--TODO - Add proper translation--> <!--TODO - Add proper translation-->
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string>
</resources>
\ No newline at end of file <!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string> <!-- TODO - Add proper translation -->
</resources>
...@@ -227,6 +227,8 @@ ...@@ -227,6 +227,8 @@
<string name="action_title_editing">संपादन संदेश</string> <string name="action_title_editing">संपादन संदेश</string>
<string name="action_msg_add_reaction">प्रतिक्रिया जोड़ें</string> <string name="action_msg_add_reaction">प्रतिक्रिया जोड़ें</string>
<string name="action_msg_copy_permalink">परमालिंक कॉपी करें</string> <string name="action_msg_copy_permalink">परमालिंक कॉपी करें</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">संपादन की अनुमति नहीं है</string> <string name="permission_editing_not_allowed">संपादन की अनुमति नहीं है</string>
...@@ -333,4 +335,15 @@ ...@@ -333,4 +335,15 @@
<string name="message_information_title">संदेश की जानकारी</string> <string name="message_information_title">संदेश की जानकारी</string>
<string name="msg_log_out">लॉग आउट कर रहा हूं…</string> <string name="msg_log_out">लॉग आउट कर रहा हूं…</string>
<string name="message_room_changed_privacy">%2$s ने रूम का प्रकार बदलकर %1$s किया </string> <string name="message_room_changed_privacy">%2$s ने रूम का प्रकार बदलकर %1$s किया </string>
<!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string>
</resources> </resources>
...@@ -222,7 +222,9 @@ ...@@ -222,7 +222,9 @@
<string name="action_msg_share">Condividi</string> <string name="action_msg_share">Condividi</string>
<string name="action_title_editing">Modifica messaggio</string> <string name="action_title_editing">Modifica messaggio</string>
<string name="action_msg_add_reaction">Aggiungi reazione</string> <string name="action_msg_add_reaction">Aggiungi reazione</string>
<string name="action_msg_copy_permalink">Copia permalink</string>3 <string name="action_msg_copy_permalink">Copia permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">La modifica non è consentita</string> <string name="permission_editing_not_allowed">La modifica non è consentita</string>
...@@ -329,4 +331,14 @@ ...@@ -329,4 +331,14 @@
<string name="message_information_title">Informazioni Messaggio</string> <string name="message_information_title">Informazioni Messaggio</string>
<string name="message_room_changed_privacy">Il tipo di stanza è cambiato in: %1$s da %2$s</string> <string name="message_room_changed_privacy">Il tipo di stanza è cambiato in: %1$s da %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string> <!-- TODO - Add proper translation -->
</resources> </resources>
...@@ -228,6 +228,8 @@ ...@@ -228,6 +228,8 @@
<string name="action_title_editing">メッセージの編集</string> <string name="action_title_editing">メッセージの編集</string>
<string name="action_msg_add_reaction">リアクションする</string> <string name="action_msg_add_reaction">リアクションする</string>
<string name="action_msg_copy_permalink">パーマリンクのコピー</string> <string name="action_msg_copy_permalink">パーマリンクのコピー</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">編集は許可されていません</string> <string name="permission_editing_not_allowed">編集は許可されていません</string>
...@@ -336,4 +338,14 @@ ...@@ -336,4 +338,14 @@
<string name="message_room_changed_privacy">ルームタイプを %2$s から %1$s に変更しました</string> <string name="message_room_changed_privacy">ルームタイプを %2$s から %1$s に変更しました</string>
</resources> <!-- User Details -->
\ No newline at end of file <string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources>
...@@ -225,6 +225,8 @@ ...@@ -225,6 +225,8 @@
<string name="action_title_editing">Editando mensagem</string> <string name="action_title_editing">Editando mensagem</string>
<string name="action_msg_add_reaction">Adicionar reação</string> <string name="action_msg_add_reaction">Adicionar reação</string>
<string name="action_msg_copy_permalink">Copiar permalink</string> <string name="action_msg_copy_permalink">Copiar permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Reportar</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Edição não permitida</string> <string name="permission_editing_not_allowed">Edição não permitida</string>
...@@ -332,4 +334,15 @@ ...@@ -332,4 +334,15 @@
<string name="msg_log_out">Deslogando…</string> <string name="msg_log_out">Deslogando…</string>
<string name="msg_sent_attachment">Enviou um arquivo</string> <string name="msg_sent_attachment">Enviou um arquivo</string>
<string name="message_room_changed_privacy">O tipo da sala mudou para: %1$s por %2$s</string> <string name="message_room_changed_privacy">O tipo da sala mudou para: %1$s por %2$s</string>
<!-- User Details -->
<string name="message">Mensagem</string>
<string name="timezone">Fuso horário</string>
<string name="error_opening_dm">Algo deu errado quando tentamos abrir esta conversa…</string>
<string name="retry">Retentar</string>
<!-- Report -->
<string name="submit">Enviar</string>
<string name="required">*obrigatório</string>
<string name="report_sent">A mensagem foi reportada!</string>
</resources> </resources>
...@@ -224,6 +224,8 @@ ...@@ -224,6 +224,8 @@
<string name="action_title_editing">Редактирование сообщения</string> <string name="action_title_editing">Редактирование сообщения</string>
<string name="action_msg_add_reaction">Отреагировать</string> <string name="action_msg_add_reaction">Отреагировать</string>
<string name="action_msg_copy_permalink">Копировать ссылку</string> <string name="action_msg_copy_permalink">Копировать ссылку</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Редактирование запрещено</string> <string name="permission_editing_not_allowed">Редактирование запрещено</string>
...@@ -330,4 +332,15 @@ ...@@ -330,4 +332,15 @@
<string name="message_information_title">Информация о прочтении</string> <string name="message_information_title">Информация о прочтении</string>
<string name="msg_log_out">Выходим…</string> <string name="msg_log_out">Выходим…</string>
<string name="message_room_changed_privacy">Тип канала изменен на: %1$s пользователем %2$s</string> <string name="message_room_changed_privacy">Тип канала изменен на: %1$s пользователем %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources> </resources>
...@@ -228,6 +228,8 @@ ...@@ -228,6 +228,8 @@
<string name="action_msg_add_reaction">Tepki Ekle</string> <string name="action_msg_add_reaction">Tepki Ekle</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Düzenlemeye izin verilmiyor</string> <string name="permission_editing_not_allowed">Düzenlemeye izin verilmiyor</string>
...@@ -332,6 +334,16 @@ ...@@ -332,6 +334,16 @@
<string name="notif_success_sending">Mesaj %1$s\'a gönderildi!</string> <string name="notif_success_sending">Mesaj %1$s\'a gönderildi!</string>
<string name="read_by">ile oku</string> <string name="read_by">ile oku</string>
<string name="message_information_title">Mesaj bilgisi</string> <string name="message_information_title">Mesaj bilgisi</string>
<!--TODO - Add proper translation--> <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">Room type changed to: %1$s by %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources> </resources>
...@@ -224,6 +224,8 @@ ...@@ -224,6 +224,8 @@
<string name="action_msg_add_reaction">Відреагувати</string> <string name="action_msg_add_reaction">Відреагувати</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Редагування заборонено</string> <string name="permission_editing_not_allowed">Редагування заборонено</string>
...@@ -330,6 +332,16 @@ ...@@ -330,6 +332,16 @@
<string name="message_information_title">Інформація про прочитання</string> <string name="message_information_title">Інформація про прочитання</string>
<string name="msg_log_out">Виходимо…</string> <string name="msg_log_out">Виходимо…</string>
<string name="msg_sent_attachment">Долучення відправлено</string> <string name="msg_sent_attachment">Долучення відправлено</string>
<!--TODO - Add proper translation--> <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">Room type changed to: %1$s by %2$s</string>
<!-- User Details -->
<string name="message">Message</string>
<string name="timezone">Timezone</string>
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string> <!-- TODO - Add proper translation -->
</resources> </resources>
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
<!-- Text colors --> <!-- Text colors -->
<color name="colorPrimaryText">#DE000000</color> <color name="colorPrimaryText">#DE000000</color>
<color name="colorSecondaryText">#FF787878</color> <color name="colorSecondaryText">#FF787878</color>
<color name="colorLightGrey">#F4F5F7</color>
<color name="colorSecondaryTextLight">#FFC1C1C1</color> <color name="colorSecondaryTextLight">#FFC1C1C1</color>
<color name="colorTimestampText">#FF9DA2A9</color>
<color name="colorTimestampTextUnread">#FF5699FF</color>
<color name="colorLastMessageText">#99000000</color>
<!-- User status colors --> <!-- User status colors -->
<color name="colorUserStatusOnline">#2FE1A8</color> <color name="colorUserStatusOnline">#2FE1A8</color>
...@@ -53,6 +55,8 @@ ...@@ -53,6 +55,8 @@
<color name="colorDivider">#1F000000</color> <color name="colorDivider">#1F000000</color>
<color name="colorLightGrey">#F4F5F7</color>
<!-- Suggestions --> <!-- Suggestions -->
<color name="suggestion_background_color">@color/colorWhite</color> <color name="suggestion_background_color">@color/colorWhite</color>
......
...@@ -203,7 +203,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -203,7 +203,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="msg_view_more">view more</string> <string name="msg_view_more">view more</string>
<string name="msg_view_less">view less</string> <string name="msg_view_less">view less</string>
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <string name="msg_muted_on_this_channel">You are muted on this channel</string>
<!-- Preferences messages --> <!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string> <string name="msg_analytics_tracking">Analytics tracking</string>
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string> <string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string>
...@@ -240,6 +240,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -240,6 +240,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="action_title_editing">Editing Message</string> <string name="action_title_editing">Editing Message</string>
<string name="action_msg_add_reaction">Add reaction</string> <string name="action_msg_add_reaction">Add reaction</string>
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Editing is not allowed</string> <string name="permission_editing_not_allowed">Editing is not allowed</string>
...@@ -346,5 +347,17 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -346,5 +347,17 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="message_information_title">Message information</string> <string name="message_information_title">Message information</string>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string>
<string name="foss" tools:ignore="MissingTranslation">(FOSS)</string> <string name="foss" translatable="false">(FOSS)</string>
</resources>
\ No newline at end of file <!-- User Details -->
<string name="message">Message</string>
<string name="timezone">Timezone</string>
<string name="status" translatable="false">Status</string>
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string>
<string name="retry">Retry</string>
<!-- Report -->
<string name="submit">Submit</string>
<string name="required">*required</string>
<string name="report_sent">Your report has been sent!</string>
</resources>
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
<item name="android:layout_width">wrap_content</item> <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:textSize">24sp</item> <item name="android:textSize">24sp</item>
<item name="android:lineSpacingExtra">4sp</item>
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textColor">@color/colorPrimary</item> <item name="android:textColor">@color/colorPrimary</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
...@@ -29,7 +28,6 @@ ...@@ -29,7 +28,6 @@
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:lineSpacingExtra">4sp</item>
<item name="android:textColor">#FF54585E</item> <item name="android:textColor">#FF54585E</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
</style> </style>
...@@ -39,7 +37,6 @@ ...@@ -39,7 +37,6 @@
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
<item name="android:textColor">@color/colorAccent</item> <item name="android:textColor">@color/colorAccent</item>
<item name="android:letterSpacing">0.04</item>
<item name="android:maxLines">1</item> <item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item> <item name="android:ellipsize">end</item>
</style> </style>
...@@ -53,7 +50,6 @@ ...@@ -53,7 +50,6 @@
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorAuthenticationSecondaryText</item> <item name="android:textColor">@color/colorAuthenticationSecondaryText</item>
<item name="android:letterSpacing">0.04</item>
<item name="android:maxLines">1</item> <item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item> <item name="android:ellipsize">end</item>
</style> </style>
...@@ -63,7 +59,6 @@ ...@@ -63,7 +59,6 @@
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
<item name="android:textColorHint">@color/colorAuthenticationSecondaryText</item> <item name="android:textColorHint">@color/colorAuthenticationSecondaryText</item>
<item name="android:lineSpacingExtra">3sp</item>
</style> </style>
<style name="Authentication.EditText.Border" parent="Widget.AppCompat.EditText"> <style name="Authentication.EditText.Border" parent="Widget.AppCompat.EditText">
...@@ -87,7 +82,6 @@ ...@@ -87,7 +82,6 @@
<item name="android:fontFamily">sans-serif-medium</item> <item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorWhite</item> <item name="android:textColor">@color/colorWhite</item>
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>
<item name="android:background">@drawable/rounded_color_accent</item> <item name="android:background">@drawable/rounded_color_accent</item>
</style> </style>
...@@ -100,15 +94,66 @@ ...@@ -100,15 +94,66 @@
<item name="android:textSize">18sp</item> <item name="android:textSize">18sp</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:lineSpacingExtra">2sp</item>
</style> </style>
// REMARK: To be removed as soon as we have our loading view.
<style name="Authentication.AVLoadingIndicatorView" parent="AVLoadingIndicatorView"> <style name="Authentication.AVLoadingIndicatorView" parent="AVLoadingIndicatorView">
<item name="android:layout_width">wrap_content</item> <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="indicatorColor">@color/colorPrimary</item> <item name="indicatorColor">@color/colorPrimary</item>
<item name="indicatorName">BallPulseIndicator</item> <item name="indicatorName">BallPulseIndicator</item>
</style> </style>
<!-- End Authentication -->
<!-- Chat list -->
<style name="ChatList.ChatName.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">16sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
</style>
<style name="ChatList.ChatName.Unread.TextView" parent="ChatList.ChatName.TextView">
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">bold</item>
</style>
<style name="ChatList.LastMessage.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorLastMessageText</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
</style>
<style name="ChatList.LastMessage.Unread.TextView" parent="ChatList.LastMessage.TextView">
<item name="android:fontFamily">sans-serif-medium</item>
</style>
<style name="ChatList.Timestamp.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">12sp</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorTimestampText</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
</style>
<style name="ChatList.Timestamp.Unread.TextView" parent="ChatList.Timestamp.TextView">
<item name="android:textColor">@color/colorTimestampTextUnread</item>
</style>
<style name="ChatList.Badge.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorWhite</item>
<item name="android:gravity">center</item>
</style>
<!-- End chat list -->
<style name="EditText.Password" parent="TextAppearance.AppCompat"> <style name="EditText.Password" parent="TextAppearance.AppCompat">
<!-- Hint color and label color in FALSE state --> <!-- Hint color and label color in FALSE state -->
...@@ -118,13 +163,6 @@ ...@@ -118,13 +163,6 @@
<item name="colorControlActivated">@color/colorPrimaryDark</item> <item name="colorControlActivated">@color/colorPrimaryDark</item>
</style> </style>
<style name="AuthenticationLabel" parent="TextAppearance.AppCompat.Medium">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">50dp</item>
<item name="android:layout_marginStart">@dimen/screen_edge_left_and_right_margins</item>
<item name="android:paddingStart">@dimen/edit_text_margin</item>
</style>
<style name="ChatRoom.SearchView" parent="Widget.AppCompat.SearchView"> <style name="ChatRoom.SearchView" parent="Widget.AppCompat.SearchView">
<item name="queryHint">@string/title_search_message</item> <item name="queryHint">@string/title_search_message</item>
<item name="searchIcon">@drawable/ic_search_white_24dp</item> <item name="searchIcon">@drawable/ic_search_white_24dp</item>
...@@ -132,13 +170,11 @@ ...@@ -132,13 +170,11 @@
<item name="closeIcon">@drawable/ic_close_white_24dp</item> <item name="closeIcon">@drawable/ic_close_white_24dp</item>
</style> </style>
<style name="ChatRooms.Header" parent="TextAppearance.AppCompat.Headline"> <style name="ChatRoom.Timestamp.TextView" parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">16sp</item> <item name="android:textSize">10sp</item>
</style> </style>
<style name="ChatRoom.Name.TextView" parent="TextAppearance.AppCompat.Title"> <style name="ChatRooms.Header" parent="TextAppearance.AppCompat.Headline">
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
</style> </style>
...@@ -173,10 +209,6 @@ ...@@ -173,10 +209,6 @@
<item name="android:textColor">@color/colorPrimaryText</item> <item name="android:textColor">@color/colorPrimaryText</item>
</style> </style>
<style name="Timestamp.TextView" parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">10sp</item>
</style>
// REMARK: To be removed. // REMARK: To be removed.
<style name="Profile.EditText" parent="Authentication.EditText.Border"> <style name="Profile.EditText" parent="Authentication.EditText.Border">
<item name="android:background">@drawable/style_edit_text_profile</item> <item name="android:background">@drawable/style_edit_text_profile</item>
......
...@@ -26,7 +26,7 @@ ext { ...@@ -26,7 +26,7 @@ ext {
playServices : '16.0.0', playServices : '16.0.0',
exoPlayer : '2.8.2', exoPlayer : '2.8.2',
flexbox : '1.1.0', flexbox : '1.1.0',
material : '1.0.0-beta01', material : '1.0.0',
room : '2.0.0', room : '2.0.0',
lifecycle : '2.0.0', lifecycle : '2.0.0',
......
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