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 {
applicationId "chat.rocket.android"
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
versionCode 2051
versionCode 2052
versionName "3.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
......
......@@ -93,6 +93,16 @@
android:name=".settings.password.ui.PasswordActivity"
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
android:name=".push.DirectReplyReceiver"
android:enabled="true"
......
......@@ -19,7 +19,6 @@ import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.coroutines.experimental.Job
import javax.inject.Inject
class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
......@@ -27,7 +26,6 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
@Inject
lateinit var presenter: AuthenticationPresenter
val job = Job()
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
......
......@@ -251,6 +251,9 @@ class ChatRoomAdapter(
R.id.action_message_permalink -> {
actionSelectListener?.copyPermalink(id)
}
R.id.action_message_report -> {
actionSelectListener?.reportMessage(id)
}
else -> {
TODO("Not implemented")
}
......@@ -260,16 +263,29 @@ class ChatRoomAdapter(
}
interface OnActionSelected {
fun showMessageInfo(id: String)
fun citeMessage(roomName: String, roomType: String, messageId: String, mentionAuthor: Boolean)
fun copyMessage(id: String)
fun editMessage(roomId: String, messageId: String, text: String)
fun toogleStar(id: String, star: Boolean)
fun tooglePin(id: String, pin: Boolean)
fun deleteMessage(roomId: String, id: String)
fun showReactions(id: String)
fun openDirectMessage(roomName: String, message: String)
fun sendMessage(chatRoomId: String, text: String)
fun copyPermalink(id: String)
fun reportMessage(id: String)
}
}
package chat.rocket.android.chatroom.adapter
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.text.Spannable
......@@ -10,6 +11,7 @@ import androidx.core.view.isVisible
import chat.rocket.android.R
import chat.rocket.android.chatroom.uimodel.MessageUiModel
import chat.rocket.android.emoji.EmojiReactionListener
import chat.rocket.android.userdetails.ui.userDetailsIntent
import chat.rocket.core.model.isSystemMessage
import com.bumptech.glide.load.resource.gif.GifDrawable
import kotlinx.android.synthetic.main.avatar.view.*
......@@ -70,7 +72,23 @@ class MessageViewHolder(
)
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?) {
......
......@@ -9,9 +9,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.ChatRoomDao
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
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.PermissionsInteractor
import chat.rocket.android.server.domain.SettingsRepository
......
......@@ -60,6 +60,7 @@ import chat.rocket.core.internal.rest.joinChat
import chat.rocket.core.internal.rest.markAsRead
import chat.rocket.core.internal.rest.messages
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.searchMessages
import chat.rocket.core.internal.rest.sendMessage
......@@ -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() {
view.showFileSelection(settings.uploadMimeTypeFilter())
}
......
......@@ -68,17 +68,18 @@ import chat.rocket.android.helper.ImageHelper
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.MessageParser
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.content
import chat.rocket.android.util.extensions.fadeIn
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.inflate
import chat.rocket.android.util.extensions.rotateBy
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
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.roomTypeOf
import chat.rocket.core.internal.realtime.socket.model.State
......@@ -86,19 +87,16 @@ import dagger.android.support.AndroidSupportInjection
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
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_row_item.*
import kotlinx.android.synthetic.main.emoji_row_item.view.*
import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_attachment_options.*
import kotlinx.android.synthetic.main.message_composer.*
import kotlinx.android.synthetic.main.message_list.*
import kotlinx.android.synthetic.main.reaction_praises_list_item.view.*
import timber.log.Timber
import java.io.File
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.atomic.AtomicInteger
import javax.inject.Inject
......@@ -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_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
class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener,
......@@ -842,9 +840,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} else {
input_container.isVisible = true
text_room_is_read_only.isVisible = false
button_send.isVisible = false
button_show_attachment_options.alpha = 1f
button_show_attachment_options.isVisible = true
activity?.supportFragmentManager?.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() {
......@@ -862,7 +858,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
)
subscribeComposeTextMessage()
getUnfinishedMessage()
emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container))
emojiKeyboardPopup.listener = this
text_message.listener = object : ComposerEditText.ComposerEditTextListener {
......@@ -1172,4 +1167,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override fun sendMessage(chatRoomId: String, text: String) {
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) {
internal fun ChatRoomFragment.setOnMenuItemClickListener(item: MenuItem) {
when (item.itemId) {
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT -> presenter.toggleFavoriteChatRoom(
MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT -> presenter.toggleFavoriteChatRoom(
chatRoomId,
isFavorite
)
......@@ -87,7 +87,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) {
if (isFavorite) {
menu.add(
Menu.NONE,
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT,
MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT,
Menu.NONE,
R.string.title_unfavorite_chat
).setIcon(R.drawable.ic_star_yellow_24dp)
......@@ -95,7 +95,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) {
} else {
menu.add(
Menu.NONE,
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT,
MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT,
Menu.NONE,
R.string.title_favorite_chat
).setIcon(R.drawable.ic_star_border_white_24dp)
......
......@@ -21,7 +21,8 @@ data class MessageUiModel(
var isFirstUnread: Boolean,
override var isTemporary: Boolean = false,
override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var permalink: String
override var permalink: String,
val subscriptionId: String
) : BaseMessageUiModel<Message> {
override val viewType: Int
get() = BaseUiModel.ViewType.MESSAGE.viewType
......
......@@ -456,7 +456,8 @@ class UiModelMapper @Inject constructor(
messageId = message.id, avatar = avatar!!, time = time, senderName = sender,
content = content, isPinned = message.pinned, currentDayMarkerText = dayMarkerText,
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 {
......
......@@ -2,9 +2,6 @@ package chat.rocket.android.chatrooms.adapter
import android.app.Application
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.chatrooms.adapter.model.RoomUiModel
import chat.rocket.android.db.model.ChatRoom
......@@ -32,18 +29,13 @@ class RoomUiModelMapper(
private val serverUrl: String,
private val permissions: PermissionsInteractor
) {
private val nameUnreadColor = ContextCompat.getColor(context, R.color.colorPrimaryText)
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() }
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)
var lastType: String? = null
rooms.forEach { room ->
......@@ -72,7 +64,7 @@ class RoomUiModelMapper(
private fun mapUser(user: User): RoomUiModel {
return with(user) {
val name = mapName(user.username!!, user.name, false)
val name = mapName(user.username!!, user.name)
val status = user.status
val avatar = serverUrl.avatarUrl(user.username!!)
val username = user.username!!
......@@ -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) {
RoomUiModel(
id = id,
name = name!!,
type = type,
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,
isDirectMessage = type is RoomType.DirectMessage)} else { null },
isDirectMessage = type is RoomType.DirectMessage
)
} else {
null
},
muted = muted.orEmpty(),
writable = isChannelWritable(muted)
)
}
}
fun map(chatRoom: ChatRoom, showLastMessage:Boolean = true): RoomUiModel {
fun map(chatRoom: ChatRoom, showLastMessage: Boolean = true): RoomUiModel {
return with(chatRoom.chatRoom) {
val isUnread = alert || unread > 0
val type = roomTypeOf(type)
val status = chatRoom.status?.let { userStatusOf(it) }
val roomName = mapName(name, fullname, isUnread)
val timestamp = mapDate(lastMessageTimestamp ?: updatedAt, isUnread)
val roomName = mapName(name, fullname)
val timestamp = mapDate(lastMessageTimestamp ?: updatedAt)
val avatar = if (type is RoomType.DirectMessage) {
serverUrl.avatarUrl(name)
} else {
serverUrl.avatarUrl(name, isGroupOrChannel = true)
}
val unread = mapUnread(unread)
val lastMessage = if(showLastMessage) { mapLastMessage(lastMessageUserId, chatRoom.lastMessageUserName,
chatRoom.lastMessageUserFullName, lastMessageText, isUnread,
type is RoomType.DirectMessage) } else { null }
val lastMessage = if (showLastMessage) {
mapLastMessage(
lastMessageUserId,
chatRoom.lastMessageUserName,
chatRoom.lastMessageUserFullName,
lastMessageText,
type is RoomType.DirectMessage
)
} else {
null
}
val hasMentions = mapMentions(userMentions, groupMentions)
val open = open
val lastMessageMarkdown = lastMessage?.let { Markwon.markdown(context, it.toString()).toString() }
val lastMessageMarkdown =
lastMessage?.let { Markwon.markdown(context, it.toString()).toString() }
RoomUiModel(
id = id,
......@@ -132,6 +139,7 @@ class RoomUiModelMapper(
open = open,
date = timestamp,
unread = unread,
mentions = hasMentions,
alert = isUnread,
lastMessage = lastMessageMarkdown,
status = status,
......@@ -158,47 +166,37 @@ class RoomUiModelMapper(
}
}
private fun mapLastMessage(userId: String?, name: String?, fullName: String?, text: String?,
unread: Boolean = false,
isDirectMessage: Boolean = false): CharSequence? {
private fun mapLastMessage(
userId: String?,
name: String?,
fullName: String?,
text: String?,
isDirectMessage: Boolean = false
): CharSequence? {
return if (!settings.showLastMessage()) {
null
} else if (name != null && text != null) {
val user = if (currentUser != null && currentUser!!.id == userId) {
"${context.getString(R.string.msg_you)}: "
} else {
if (isDirectMessage) "" else "${mapName(name, fullName, unread)}: "
}
val color = if (unread) messageUnreadColor else messageColor
SpannableStringBuilder()
.color(color) {
bold { append(user) }
append(text)
if (isDirectMessage) "" else "${mapName(name, fullName)}: "
}
SpannableStringBuilder().append(user).append(text)
} else {
context.getText(R.string.msg_no_messages_yet)
}
}
private fun mapName(name: String, fullName: String?, unread: Boolean): CharSequence {
val roomName = if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
private fun mapName(name: String, fullName: String?): CharSequence {
return if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
fullName ?: name
} else {
name
}
val color = if (unread) nameUnreadColor else nameColor
return SpannableStringBuilder()
.color(color) {
append(roomName)
}
}
private fun mapUnread(unread: Long): String? {
return when(unread) {
return when (unread) {
0L -> null
in 1..99 -> unread.toString()
else -> context.getString(R.string.msg_more_than_ninety_nine_unread_messages)
......@@ -206,12 +204,14 @@ class RoomUiModelMapper(
}
}
private fun mapDate(date: Long?, unread: Boolean): CharSequence? {
return date?.localDateTime()?.date(context)?.let {
val color = if (unread) dateUnreadColor else dateColor
SpannableStringBuilder().color(color) {
append(it)
private fun mapMentions(userMentions: Long?, groupMentions: Long?): Boolean {
if (userMentions != null && groupMentions != null) {
if (userMentions > 0 || groupMentions > 0) {
return true
}
}
return false
}
private fun mapDate(date: Long?): CharSequence? = date?.localDateTime()?.date(context)
}
......@@ -4,6 +4,7 @@ import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.view.View
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
......@@ -11,19 +12,16 @@ import chat.rocket.common.model.RoomType
import chat.rocket.common.model.UserStatus
import kotlinx.android.synthetic.main.item_chat.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 channelUnread: Drawable = resources.getDrawable(R.drawable.ic_hashtag_black_12dp)
private val channel: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp)
private val groupUnread: Drawable = resources.getDrawable(R.drawable.ic_lock_black_12_dp)
private val group: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp)
private val online: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp)
private val away: Drawable = resources.getDrawable(R.drawable.ic_status_away_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)
private val channelIcon: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp)
private val groupIcon: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp)
private val onlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp)
private val awayIcon: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp)
private val busyIcon: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp)
private val offlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp)
override fun bindViews(data: RoomItemHolder) {
val room = data.data
......@@ -31,53 +29,59 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit
image_avatar.setImageURI(room.avatar)
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) {
text_last_message.isVisible = true
text_last_message.text = room.lastMessage
text_last_message.isVisible = true
} else {
text_last_message.isGone = true
}
if (room.date != null) {
text_last_message_date_time.isVisible = true
text_last_message_date_time.text = room.date
text_timestamp.text = room.date
text_timestamp.isVisible = true
} 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.text = room.unread
} 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) {
image_chat_icon.setImageDrawable(getStatusDrawable(room.status))
} else {
image_chat_icon.setImageDrawable(getRoomDrawable(room.type, room.alert))
}
setOnClickListener {
listener(room)
}
setOnClickListener { listener(room) }
}
}
private fun getRoomDrawable(type: RoomType, alert: Boolean): Drawable? {
return when(type) {
is RoomType.Channel -> if (alert) channelUnread else channel
is RoomType.PrivateGroup -> if (alert) groupUnread else group
private fun getRoomDrawable(type: RoomType): Drawable? {
return when (type) {
is RoomType.Channel -> channelIcon
is RoomType.PrivateGroup -> groupIcon
else -> null
}
}
private fun getStatusDrawable(status: UserStatus): Drawable {
return when(status) {
is UserStatus.Online -> online
is UserStatus.Away -> away
is UserStatus.Busy -> busy
else -> offline
return when (status) {
is UserStatus.Online -> onlineIcon
is UserStatus.Away -> awayIcon
is UserStatus.Busy -> busyIcon
else -> offlineIcon
}
}
}
\ No newline at end of file
......@@ -6,7 +6,8 @@ import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
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 {
setHasStableIds(true)
......@@ -40,16 +41,16 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : RecyclerView.A
override fun getItemId(position: Int): Long {
val item = values[position]
return when(item) {
is HeaderItemHolder -> item.data.hashCode().toLong()
return when (item) {
is RoomItemHolder -> item.data.id.hashCode().toLong()
is HeaderItemHolder -> item.data.hashCode().toLong()
is LoadingItemHolder -> "loading".hashCode().toLong()
else -> throw IllegalStateException("View type must be either Room, Header or Loading")
}
}
override fun getItemViewType(position: Int): Int {
return when(values[position]) {
return when (values[position]) {
is RoomItemHolder -> VIEW_TYPE_ROOM
is HeaderItemHolder -> VIEW_TYPE_HEADER
is LoadingItemHolder -> VIEW_TYPE_LOADING
......
......@@ -12,6 +12,7 @@ data class RoomUiModel(
val date: CharSequence? = null,
val unread: String? = null,
val alert: Boolean = false,
val mentions: Boolean = false,
val lastMessage: CharSequence? = null,
val status: UserStatus? = 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
import chat.rocket.android.settings.di.SettingsFragmentProvider
import chat.rocket.android.settings.password.di.PasswordFragmentProvider
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 dagger.Module
import dagger.android.ContributesAndroidInjector
......@@ -108,6 +110,11 @@ abstract class ActivityBuilder {
@ContributesAndroidInjector(modules = [MessageInfoFragmentProvider::class])
abstract fun bindMessageInfoActiviy(): MessageInfoActivity
@PerActivity
@ContributesAndroidInjector(modules = [DrawModule::class])
abstract fun bindDrawingActivity(): DrawingActivity
@PerActivity
@ContributesAndroidInjector(modules = [UserDetailsModule::class])
abstract fun bindUserDetailsActivity(): UserDetailsActivity
}
......@@ -29,7 +29,7 @@ abstract class UserDao : BaseDao<UserEntity> {
abstract fun findUser(id: String): String?
@Query("SELECT * FROM users WHERE ID = :id")
abstract fun getUser(id:String): UserEntity?
abstract fun getUser(id: String): UserEntity?
@Transaction
open fun upsert(user: BaseUserEntity) {
......
package chat.rocket.android.members.presentation
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.members.ui.TAG_MEMBER_BOTTOM_SHEET_FRAGMENT
import chat.rocket.android.members.ui.newInstance
import chat.rocket.android.userdetails.ui.userDetailsIntent
class MembersNavigator(internal val activity: ChatDetailsActivity) {
fun toMemberDetails(avatarUri: String, realName: String, username: String, email: String, utcOffset: String) {
fun toMemberDetails(userId: String) {
activity.apply {
newInstance(avatarUri, realName, username, email, utcOffset)
.show(supportFragmentManager, TAG_MEMBER_BOTTOM_SHEET_FRAGMENT)
startActivity(this.userDetailsIntent(userId, ""))
}
}
}
......@@ -59,12 +59,6 @@ class MembersPresenter @Inject constructor(
}
fun toMemberDetails(memberUiModel: MemberUiModel) {
navigator.toMemberDetails(
memberUiModel.avatarUri.toString(),
memberUiModel.realName.toString(),
"@${memberUiModel.username}",
memberUiModel.email ?: "",
memberUiModel.utcOffset.toString()
)
navigator.toMemberDetails(memberUiModel.userId)
}
}
......@@ -11,6 +11,7 @@ class MemberUiModel(
private val settings: Map<String, Value<Any>>,
private val baseUrl: String?
) {
val userId: String = member.id
val avatarUri: String?
val displayName: String
val realName: String?
......
......@@ -7,7 +7,10 @@ import chat.rocket.common.model.User
import chat.rocket.core.model.Value
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 val baseUrl = settings.baseUrl()
......
......@@ -35,10 +35,6 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
private var actionMode: ActionMode? = null
private val disposables = CompositeDisposable()
companion object {
fun newInstance() = PasswordFragment()
}
override fun onCreate(savedInstanceState: Bundle?) {
AndroidSupportInjection.inject(this)
super.onCreate(savedInstanceState)
......@@ -143,4 +139,8 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
actionMode = (activity as PasswordActivity).startSupportActionMode(this)
}
}
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
}
<?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"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
android:shape="rectangle">
<solid android:color="@color/colorAccent" />
<corners android:radius="4dp" />
</shape>
......@@ -6,9 +6,11 @@
android:orientation="vertical"
android:theme="@style/AppTheme"
tools:context=".settings.password.ui.PasswordActivity">
<include
android:id="@+id/layout_app_bar"
layout="@layout/app_bar_password" />
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
......
<?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 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
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: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
android:id="@+id/image_avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:roundedCornerRadius="3dp" />
app:roundedCornerRadius="4dp" />
<ImageView
android:id="@+id/image_chat_icon"
......@@ -27,65 +27,50 @@
app:layout_constraintBottom_toBottomOf="@+id/text_chat_name"
app:layout_constraintStart_toEndOf="@+id/image_avatar"
app:layout_constraintTop_toTopOf="@+id/text_chat_name"
tools:src="@drawable/ic_hashtag_unread_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" />
tools:src="@drawable/ic_hashtag_12dp" />
<TextView
android:id="@+id/text_chat_name"
style="@style/ChatRoom.Name.TextView"
style="@style/ChatList.ChatName.TextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/text_view_drawable_padding"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textDirection="locale"
android:textColor="@color/colorSecondaryText"
app:layout_constraintBottom_toTopOf="@+id/text_last_message"
app:layout_constraintEnd_toStartOf="@+id/text_last_message_date_time"
app:layout_constraintEnd_toStartOf="@+id/text_timestamp"
app:layout_constraintStart_toEndOf="@+id/image_chat_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="general" />
tools:text="Margaret Hanson" />
<TextView
android:id="@+id/text_last_message_date_time"
style="@style/Timestamp.TextView"
android:id="@+id/text_timestamp"
style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:gravity="center"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="@+id/layout_unread_messages_badge"
android:textDirection="locale"
app:layout_constraintBaseline_toBaselineOf="@+id/text_chat_name"
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:ellipsize="end"
android:maxLines="2"
android:layout_marginEnd="12dp"
android:textDirection="locale"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge"
app:layout_constraintTop_toTopOf="@+id/text_chat_name"
tools:text="11:45 AM" />
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" />
<include
android:id="@+id/layout_unread_messages_badge"
layout="@layout/unread_messages_badge"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_width="21dp"
android:layout_height="21dp"
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>
\ No newline at end of file
......@@ -92,11 +92,11 @@
android:id="@+id/message_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="16dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@+id/layout_avatar"
app:layout_constraintStart_toEndOf="@+id/layout_avatar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/day_marker_layout">
<TextView
......@@ -104,13 +104,13 @@
style="@style/Sender.Name.TextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:layout_weight="1"
tools:text="User Name with long name" />
<TextView
android:id="@+id/text_message_time"
style="@style/Timestamp.TextView"
style="@style/ChatRoom.Timestamp.TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
......
......@@ -131,7 +131,7 @@
<TextView
android:id="@+id/text_message_time"
style="@style/Timestamp.TextView"
style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
......
......@@ -37,7 +37,7 @@
<TextView
android:id="@+id/text_message_time"
style="@style/Timestamp.TextView"
style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
......
......@@ -6,15 +6,12 @@
<TextView
android:id="@+id/text_total_unread_messages"
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="18dp"
android:layout_height="18dp"
style="@style/ChatList.Badge.TextView"
android:layout_width="21dp"
android:layout_height="21dp"
android:background="@drawable/style_total_unread_messages"
android:gravity="center"
android:textColor="@color/colorWhite"
android:textSize="10sp"
android:visibility="gone"
tools:text="99+"
tools:text="1"
tools:visibility="visible" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_message_info"
android:icon="@drawable/ic_action_message_info_outline_24dp"
android:title="@string/action_msg_info" />
<item
android:id="@+id/action_message_reply"
android:icon="@drawable/ic_action_message_reply_24dp"
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
android:id="@+id/action_message_permalink"
......@@ -27,11 +34,6 @@
android:icon="@drawable/ic_action_message_copy_24dp"
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-->
<!--android:id="@+id/action_menu_msg_share"-->
<!--andrtextIconicon="@drawable/ic_share_black_24px"-->
......@@ -48,9 +50,9 @@
android:title="@string/action_msg_pin" />
<item
android:id="@+id/action_message_edit"
android:icon="@drawable/ic_action_message_edit_24dp"
android:title="@string/action_msg_edit" />
android:id="@+id/action_message_report"
android:icon="@drawable/ic_action_message_report_24dp"
android:title="@string/action_msg_report" />
<item
android:id="@+id/action_message_delete"
......
......@@ -225,6 +225,8 @@
<string name="action_msg_add_reaction">Reaktion hinzufügen</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">Bearbeiten nicht erlaubt</string>
......@@ -329,6 +331,16 @@
<string name="notif_success_sending">Nachricht gesendet nach %1$s!</string>
<string name="read_by">Gelesen von</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>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation-->
<!-- 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>
......@@ -220,6 +220,8 @@
<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_copy_permalink">Copiar permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">La edición no és permitida</string>
......@@ -330,6 +332,16 @@
<string name="msg_file_description">Descripción del archivo</string>
<string name="msg_send">Enviar</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>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation-->
<!-- 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>
......@@ -226,6 +226,8 @@
<string name="action_msg_add_reaction">Ajouter une réaction</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">L\'édition n\'est pas autorisée</string>
......@@ -334,4 +336,15 @@
<string name="msg_sent_attachment">Envoyé un fichier</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>
......@@ -227,6 +227,8 @@
<string name="action_title_editing">संपादन संदेश</string>
<string name="action_msg_add_reaction">प्रतिक्रिया जोड़ें</string>
<string name="action_msg_copy_permalink">परमालिंक कॉपी करें</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">संपादन की अनुमति नहीं है</string>
......@@ -333,4 +335,15 @@
<string name="message_information_title">संदेश की जानकारी</string>
<string name="msg_log_out">लॉग आउट कर रहा हूं…</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>
......@@ -222,7 +222,9 @@
<string name="action_msg_share">Condividi</string>
<string name="action_title_editing">Modifica messaggio</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 -->
<string name="permission_editing_not_allowed">La modifica non è consentita</string>
......@@ -329,4 +331,14 @@
<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>
<!-- 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>
......@@ -228,6 +228,8 @@
<string name="action_title_editing">メッセージの編集</string>
<string name="action_msg_add_reaction">リアクションする</string>
<string name="action_msg_copy_permalink">パーマリンクのコピー</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">編集は許可されていません</string>
......@@ -336,4 +338,14 @@
<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> <!--TODO - Add proper translation-->
</resources>
......@@ -225,6 +225,8 @@
<string name="action_title_editing">Editando mensagem</string>
<string name="action_msg_add_reaction">Adicionar reação</string>
<string name="action_msg_copy_permalink">Copiar permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Reportar</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">Edição não permitida</string>
......@@ -332,4 +334,15 @@
<string name="msg_log_out">Deslogando…</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>
<!-- 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>
......@@ -224,6 +224,8 @@
<string name="action_title_editing">Редактирование сообщения</string>
<string name="action_msg_add_reaction">Отреагировать</string>
<string name="action_msg_copy_permalink">Копировать ссылку</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">Редактирование запрещено</string>
......@@ -330,4 +332,15 @@
<string name="message_information_title">Информация о прочтении</string>
<string name="msg_log_out">Выходим…</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>
......@@ -228,6 +228,8 @@
<string name="action_msg_add_reaction">Tepki Ekle</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">Düzenlemeye izin verilmiyor</string>
......@@ -332,6 +334,16 @@
<string name="notif_success_sending">Mesaj %1$s\'a gönderildi!</string>
<string name="read_by">ile oku</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>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation-->
<!-- 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>
......@@ -224,6 +224,8 @@
<string name="action_msg_add_reaction">Відреагувати</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">Редагування заборонено</string>
......@@ -330,6 +332,16 @@
<string name="message_information_title">Інформація про прочитання</string>
<string name="msg_log_out">Виходимо…</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>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!-- TODO - Add proper translation -->
<!-- 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>
......@@ -9,8 +9,10 @@
<!-- Text colors -->
<color name="colorPrimaryText">#DE000000</color>
<color name="colorSecondaryText">#FF787878</color>
<color name="colorLightGrey">#F4F5F7</color>
<color name="colorSecondaryTextLight">#FFC1C1C1</color>
<color name="colorTimestampText">#FF9DA2A9</color>
<color name="colorTimestampTextUnread">#FF5699FF</color>
<color name="colorLastMessageText">#99000000</color>
<!-- User status colors -->
<color name="colorUserStatusOnline">#2FE1A8</color>
......@@ -53,6 +55,8 @@
<color name="colorDivider">#1F000000</color>
<color name="colorLightGrey">#F4F5F7</color>
<!-- Suggestions -->
<color name="suggestion_background_color">@color/colorWhite</color>
......
......@@ -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_msg_add_reaction">Add reaction</string>
<string name="action_msg_copy_permalink">Copy permalink</string>
<string name="action_msg_report">Report</string>
<!-- Permission messages -->
<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
<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="foss" tools:ignore="MissingTranslation">(FOSS)</string>
<string name="foss" translatable="false">(FOSS)</string>
<!-- 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 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">24sp</item>
<item name="android:lineSpacingExtra">4sp</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:textStyle">bold</item>
......@@ -29,7 +28,6 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">16sp</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:lineSpacingExtra">4sp</item>
<item name="android:textColor">#FF54585E</item>
<item name="android:textStyle">normal</item>
</style>
......@@ -39,7 +37,6 @@
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/colorAccent</item>
<item name="android:letterSpacing">0.04</item>
<item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item>
</style>
......@@ -53,7 +50,6 @@
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorAuthenticationSecondaryText</item>
<item name="android:letterSpacing">0.04</item>
<item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item>
</style>
......@@ -63,7 +59,6 @@
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item>
<item name="android:textColorHint">@color/colorAuthenticationSecondaryText</item>
<item name="android:lineSpacingExtra">3sp</item>
</style>
<style name="Authentication.EditText.Border" parent="Widget.AppCompat.EditText">
......@@ -87,7 +82,6 @@
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorWhite</item>
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textAllCaps">false</item>
<item name="android:background">@drawable/rounded_color_accent</item>
</style>
......@@ -100,15 +94,66 @@
<item name="android:textSize">18sp</item>
<item name="android:textStyle">bold</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:lineSpacingExtra">2sp</item>
</style>
// REMARK: To be removed as soon as we have our loading view.
<style name="Authentication.AVLoadingIndicatorView" parent="AVLoadingIndicatorView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="indicatorColor">@color/colorPrimary</item>
<item name="indicatorName">BallPulseIndicator</item>
</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">
<!-- Hint color and label color in FALSE state -->
......@@ -118,13 +163,6 @@
<item name="colorControlActivated">@color/colorPrimaryDark</item>
</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">
<item name="queryHint">@string/title_search_message</item>
<item name="searchIcon">@drawable/ic_search_white_24dp</item>
......@@ -132,13 +170,11 @@
<item name="closeIcon">@drawable/ic_close_white_24dp</item>
</style>
<style name="ChatRooms.Header" parent="TextAppearance.AppCompat.Headline">
<item name="android:textSize">16sp</item>
<style name="ChatRoom.Timestamp.TextView" parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">10sp</item>
</style>
<style name="ChatRoom.Name.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<style name="ChatRooms.Header" parent="TextAppearance.AppCompat.Headline">
<item name="android:textSize">16sp</item>
</style>
......@@ -173,10 +209,6 @@
<item name="android:textColor">@color/colorPrimaryText</item>
</style>
<style name="Timestamp.TextView" parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">10sp</item>
</style>
// REMARK: To be removed.
<style name="Profile.EditText" parent="Authentication.EditText.Border">
<item name="android:background">@drawable/style_edit_text_profile</item>
......
......@@ -26,7 +26,7 @@ ext {
playServices : '16.0.0',
exoPlayer : '2.8.2',
flexbox : '1.1.0',
material : '1.0.0-beta01',
material : '1.0.0',
room : '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