Unverified Commit 5153b31e authored by Divyanshu Bhargava's avatar Divyanshu Bhargava Committed by GitHub

Merge pull request #68 from RocketChat/develop

merge
parents 6b2df2db e6d7bcea
...@@ -16,7 +16,7 @@ android { ...@@ -16,7 +16,7 @@ android {
applicationId "chat.rocket.android" applicationId "chat.rocket.android"
minSdkVersion versions.minSdk minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk
versionCode 2051 versionCode 2052
versionName "3.2.0" versionName "3.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
......
{ {
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 12, "version": 11,
"identityHash": "c533a4d17707cba4f91d35a310b8439d", "identityHash": "fb9f1c815809b0217d326452aeb34e92",
"entities": [ "entities": [
{ {
"tableName": "users", "tableName": "users",
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
}, },
{ {
"tableName": "chatrooms", "tableName": "chatrooms",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `subscriptionId` TEXT NOT NULL, `type` TEXT NOT NULL, `name` TEXT NOT NULL, `fullname` TEXT, `userId` TEXT, `ownerId` TEXT, `readonly` INTEGER, `isDefault` INTEGER, `favorite` INTEGER, `open` INTEGER NOT NULL, `alert` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `userMentions` INTEGER, `groupMentions` INTEGER, `updatedAt` INTEGER, `timestamp` INTEGER, `lastSeen` INTEGER, `lastMessageText` TEXT, `lastMessageUserId` TEXT, `lastMessageTimestamp` INTEGER, `broadcast` INTEGER, `muted` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`ownerId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`lastMessageUserId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `subscriptionId` TEXT NOT NULL, `type` TEXT NOT NULL, `name` TEXT NOT NULL, `fullname` TEXT, `userId` TEXT, `ownerId` TEXT, `readonly` INTEGER, `isDefault` INTEGER, `favorite` INTEGER, `topic` TEXT, `announcement` TEXT, `description` TEXT, `open` INTEGER NOT NULL, `alert` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `userMentions` INTEGER, `groupMentions` INTEGER, `updatedAt` INTEGER, `timestamp` INTEGER, `lastSeen` INTEGER, `lastMessageText` TEXT, `lastMessageUserId` TEXT, `lastMessageTimestamp` INTEGER, `broadcast` INTEGER, `muted` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`ownerId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`lastMessageUserId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
...@@ -121,6 +121,24 @@ ...@@ -121,6 +121,24 @@
"affinity": "INTEGER", "affinity": "INTEGER",
"notNull": false "notNull": false
}, },
{
"fieldPath": "topic",
"columnName": "topic",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "announcement",
"columnName": "announcement",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": false
},
{ {
"fieldPath": "open", "fieldPath": "open",
"columnName": "open", "columnName": "open",
...@@ -1081,7 +1099,7 @@ ...@@ -1081,7 +1099,7 @@
], ],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"c533a4d17707cba4f91d35a310b8439d\")" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"fb9f1c815809b0217d326452aeb34e92\")"
] ]
} }
} }
\ No newline at end of file
...@@ -78,6 +78,11 @@ ...@@ -78,6 +78,11 @@
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" /> android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity
android:name=".chatdetails.ui.ChatDetailsActivity"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity <activity
android:name=".chatinformation.ui.MessageInfoActivity" android:name=".chatinformation.ui.MessageInfoActivity"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
...@@ -88,6 +93,16 @@ ...@@ -88,6 +93,16 @@
android:name=".settings.password.ui.PasswordActivity" android:name=".settings.password.ui.PasswordActivity"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme" />
<activity
android:name=".userdetails.ui.UserDetailsActivity"
android:theme="@style/AppTheme"
android:windowSoftInputMode="stateAlwaysHidden">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".chatroom.ui.ChatRoomActivity" />
</activity>
<receiver <receiver
android:name=".push.DirectReplyReceiver" android:name=".push.DirectReplyReceiver"
android:enabled="true" android:enabled="true"
......
...@@ -19,7 +19,6 @@ import dagger.android.AndroidInjector ...@@ -19,7 +19,6 @@ import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.app_bar.* import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.coroutines.experimental.Job
import javax.inject.Inject import javax.inject.Inject
class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector { class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
...@@ -27,7 +26,6 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector { ...@@ -27,7 +26,6 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment> lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
@Inject @Inject
lateinit var presenter: AuthenticationPresenter lateinit var presenter: AuthenticationPresenter
val job = Job()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this) AndroidInjection.inject(this)
......
package chat.rocket.android.chatdetails.adapter
import chat.rocket.android.chatdetails.domain.Option
import chat.rocket.android.chatrooms.adapter.ItemHolder
data class OptionItemHolder(override val data: Option): ItemHolder<Option>
\ No newline at end of file
package chat.rocket.android.chatdetails.adapter
import android.content.Context
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import chat.rocket.android.R
import chat.rocket.android.chatdetails.domain.Option
import chat.rocket.android.chatrooms.adapter.ViewHolder
import kotlinx.android.synthetic.main.item_detail_option.view.*
class OptionViewHolder(
itemView: View
): ViewHolder<OptionItemHolder>(itemView) {
override fun bindViews(data: OptionItemHolder) {
val option = data.data
bindName(option, itemView.name)
bindIcon(option, itemView.icon)
itemView.setOnClickListener { option.listener() }
}
private fun bindIcon(option: Option, view: ImageView) {
val drawable = DrawableHelper.getDrawableFromId(option.icon, itemView.context)
drawable.let { image ->
val mutateDrawable = DrawableHelper.wrapDrawable(image).mutate()
DrawableHelper.tintDrawable(mutateDrawable, itemView.context, R.color.colorPrimaryText)
view.setImageDrawable(mutateDrawable)
}
}
private fun bindName(option: Option, view: TextView) {
view.text = option.name
}
}
\ No newline at end of file
package chat.rocket.android.chatdetails.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.chatdetails.presentation.ChatDetailsView
import chat.rocket.android.chatdetails.ui.ChatDetailsFragment
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 dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
@Module
class ChatDetailsFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun chatDetailsView(frag: ChatDetailsFragment): ChatDetailsView {
return frag
}
@Provides
@PerFragment
fun provideChatRoomDao(manager: DatabaseManager): ChatRoomDao = manager.chatRoomDao()
@Provides
@PerFragment
fun provideLifecycleOwner(frag: ChatDetailsFragment): LifecycleOwner {
return frag
}
@Provides
@PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
}
\ No newline at end of file
package chat.rocket.android.chatdetails.di
import chat.rocket.android.chatdetails.ui.ChatDetailsFragment
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class ChatDetailsFragmentProvider {
@ContributesAndroidInjector(modules = [ChatDetailsFragmentModule::class])
@PerFragment
abstract fun providesChatDetailsFragment(): ChatDetailsFragment
}
\ No newline at end of file
package chat.rocket.android.chatdetails.di
import chat.rocket.android.chatdetails.presentation.ChatDetailsNavigator
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.dagger.scope.PerActivity
import dagger.Module
import dagger.Provides
@Module
class ChatDetailsModule {
@Provides
@PerActivity
fun providesNavigator(activity: ChatDetailsActivity) = ChatDetailsNavigator(activity)
}
\ No newline at end of file
package chat.rocket.android.chatdetails.domain
data class ChatDetails(
val name: String?,
val fullName: String?,
val type: String?,
val topic: String?,
val announcement: String?,
val description: String?
)
\ No newline at end of file
package chat.rocket.android.chatdetails.domain
data class Option(
val name: String,
val icon: Int,
val listener: () -> Unit
)
\ No newline at end of file
package chat.rocket.android.chatdetails.presentation
import chat.rocket.android.R
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.favoritemessages.ui.TAG_FAVORITE_MESSAGES_FRAGMENT
import chat.rocket.android.files.ui.TAG_FILES_FRAGMENT
import chat.rocket.android.members.ui.TAG_MEMBERS_FRAGMENT
import chat.rocket.android.mentions.ui.TAG_MENTIONS_FRAGMENT
import chat.rocket.android.pinnedmessages.ui.TAG_PINNED_MESSAGES_FRAGMENT
import chat.rocket.android.util.extensions.addFragmentBackStack
class ChatDetailsNavigator(internal val activity: ChatDetailsActivity) {
fun toMembersList(chatRoomId: String) {
activity.addFragmentBackStack(TAG_MEMBERS_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.members.ui.newInstance(chatRoomId)
}
}
fun toMentions(chatRoomId: String) {
activity.addFragmentBackStack(TAG_MENTIONS_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.mentions.ui.newInstance(chatRoomId)
}
}
fun toPinnedMessageList(chatRoomId: String) {
activity.addFragmentBackStack(TAG_PINNED_MESSAGES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.pinnedmessages.ui.newInstance(chatRoomId)
}
}
fun toFavoriteMessageList(chatRoomId: String) {
activity.addFragmentBackStack(TAG_FAVORITE_MESSAGES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.favoritemessages.ui.newInstance(chatRoomId)
}
}
fun toFileList(chatRoomId: String) {
activity.addFragmentBackStack(TAG_FILES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.files.ui.newInstance(chatRoomId)
}
}
}
package chat.rocket.android.chatdetails.presentation
import chat.rocket.android.chatdetails.domain.ChatDetails
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull
import chat.rocket.core.internal.rest.getInfo
import chat.rocket.core.model.Room
import javax.inject.Inject
class ChatDetailsPresenter @Inject constructor(
private val view: ChatDetailsView,
private val navigator: ChatDetailsNavigator,
private val strategy: CancelStrategy,
serverInteractor: GetCurrentServerInteractor,
factory: ConnectionManagerFactory
) {
private val currentServer = serverInteractor.get()!!
private val manager = factory.create(currentServer)
private val client = manager.client
fun getDetails(chatRoomId: String, chatRoomType: String) {
launchUI(strategy) {
try {
val room = retryIO("getInfo($chatRoomId, null, $chatRoomType") {
client.getInfo(chatRoomId, null, roomTypeOf(chatRoomType))
}
view.displayDetails(roomToChatDetails(room))
} catch(e: Exception) {
e.message.let {
view.showMessage(it!!)
}.ifNull {
view.showGenericErrorMessage()
}
}
}
}
fun toFiles(chatRoomId: String) {
navigator.toFileList(chatRoomId)
}
fun toMembers(chatRoomId: String) {
navigator.toMembersList(chatRoomId)
}
fun toMentions(chatRoomId: String) {
navigator.toMentions(chatRoomId)
}
fun toPinned(chatRoomId: String) {
navigator.toPinnedMessageList(chatRoomId)
}
fun toFavorites(chatRoomId: String) {
navigator.toFavoriteMessageList(chatRoomId)
}
private fun roomToChatDetails(room: Room): ChatDetails {
return with(room) {
ChatDetails(
name = name,
fullName = fullName,
type = type.toString(),
topic = topic,
description = description,
announcement = announcement
)
}
}
}
\ No newline at end of file
package chat.rocket.android.chatdetails.presentation
import chat.rocket.android.chatdetails.domain.ChatDetails
import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView
interface ChatDetailsView: MessageView {
fun displayDetails(room: ChatDetails)
}
\ No newline at end of file
package chat.rocket.android.chatdetails.ui
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.util.extensions.addFragment
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.app_bar_chat_details.*
import javax.inject.Inject
fun Context.chatDetailsIntent(
chatRoomId: String,
chatRoomType: String,
isSubscribed: Boolean = true,
isMenuDisabled: Boolean = false
): Intent {
return Intent(this, ChatDetailsActivity::class.java).apply {
putExtra(INTENT_CHAT_ROOM_ID, chatRoomId)
putExtra(INTENT_CHAT_ROOM_TYPE, chatRoomType)
putExtra(INTENT_CHAT_IS_SUBSCRIBED, isSubscribed)
putExtra(INTENT_CHAT_DISABLED_MENU, isMenuDisabled)
}
}
private const val INTENT_CHAT_ROOM_ID = "chat_room_id"
private const val INTENT_CHAT_ROOM_TYPE = "chat_room_type"
private const val INTENT_CHAT_IS_SUBSCRIBED = "is_chat_room_subscribed"
private const val INTENT_CHAT_DISABLED_MENU = "is_menu_disabled"
class ChatDetailsActivity: AppCompatActivity(), HasSupportFragmentInjector {
@Inject
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat_details)
setupToolbar()
val chatRoomId = intent.getStringExtra(INTENT_CHAT_ROOM_ID)
requireNotNull(chatRoomId) { "no chat_room_id provided in Intent extras" }
val chatRoomType = intent.getStringExtra(INTENT_CHAT_ROOM_TYPE)
requireNotNull(chatRoomType) { "no chat_room_type provided in Intent extras" }
val isSubscribed = intent.getBooleanExtra(INTENT_CHAT_IS_SUBSCRIBED, true)
val disableMenu = intent.getBooleanExtra(INTENT_CHAT_DISABLED_MENU, false)
if (supportFragmentManager.findFragmentByTag(TAG_CHAT_DETAILS_FRAGMENT) == null) {
addFragment(TAG_CHAT_DETAILS_FRAGMENT, R.id.fragment_container) {
newInstance(chatRoomId, chatRoomType, isSubscribed, disableMenu)
}
}
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> =
fragmentDispatchingAndroidInjector
override fun onBackPressed() {
super.onBackPressed()
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
}
fun setNavigationIcon(resource: Int) {
toolbar.setNavigationIcon(resource)
}
fun setToolbarTitle(title: String) {
toolbar_title.text = title
}
private fun setupToolbar() {
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false)
setToolbarTitle(getString(R.string.title_channel_details))
setNavigationIcon(R.drawable.ic_close_white_24dp)
toolbar.setNavigationOnClickListener { onBackPressed() }
}
}
\ No newline at end of file
package chat.rocket.android.chatdetails.ui
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.chatdetails.adapter.OptionItemHolder
import chat.rocket.android.chatdetails.adapter.OptionViewHolder
import chat.rocket.android.chatdetails.domain.Option
import chat.rocket.android.util.extensions.inflate
class ChatDetailsAdapter: RecyclerView.Adapter<OptionViewHolder>() {
private val options: MutableList<Option> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder = OptionViewHolder(parent.inflate(R.layout.item_detail_option))
override fun onBindViewHolder(holder: OptionViewHolder, position: Int) = holder.bindViews(OptionItemHolder(options[position]))
override fun getItemCount(): Int = options.size
fun addOption(name: String, icon: Int, listener: () -> Unit) {
options.add(Option(name, icon, listener))
notifyDataSetChanged()
}
}
\ No newline at end of file
package chat.rocket.android.chatdetails.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import chat.rocket.android.R
import chat.rocket.android.chatdetails.domain.ChatDetails
import chat.rocket.android.chatdetails.presentation.ChatDetailsPresenter
import chat.rocket.android.chatdetails.presentation.ChatDetailsView
import chat.rocket.android.chatdetails.viewmodel.ChatDetailsViewModel
import chat.rocket.android.chatdetails.viewmodel.ChatDetailsViewModelFactory
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.widget.DividerItemDecoration
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_chat_details.*
import javax.inject.Inject
fun newInstance(
chatRoomId: String,
chatRoomType: String,
isSubscribed: Boolean,
disableMenu: Boolean
): ChatDetailsFragment {
return ChatDetailsFragment().apply {
arguments = Bundle(1).apply {
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_TYPE, chatRoomType)
putBoolean(BUNDLE_IS_SUBSCRIBED, isSubscribed)
putBoolean(BUNDLE_DISABLE_MENU, disableMenu)
}
}
}
internal const val TAG_CHAT_DETAILS_FRAGMENT = "ChatDetailsFragment"
private const val BUNDLE_CHAT_ROOM_ID = "BUNDLE_CHAT_ROOM_ID"
private const val BUNDLE_CHAT_ROOM_TYPE = "BUNDLE_CHAT_ROOM_TYPE"
private const val BUNDLE_IS_SUBSCRIBED = "BUNDLE_IS_SUBSCRIBED"
private const val BUNDLE_DISABLE_MENU = "BUNDLE_DISABLE_MENU"
class ChatDetailsFragment: Fragment(), ChatDetailsView {
@Inject
lateinit var presenter: ChatDetailsPresenter
@Inject
lateinit var factory: ChatDetailsViewModelFactory
private var adapter: ChatDetailsAdapter? = null
private lateinit var viewModel: ChatDetailsViewModel
private var chatRoomId: String? = null
private var chatRoomType: String? = null
private var isSubscribed: Boolean = true
private var disableMenu: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
val bundle = arguments
if (bundle != null) {
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID)
chatRoomType = bundle.getString(BUNDLE_CHAT_ROOM_TYPE)
isSubscribed = bundle.getBoolean(BUNDLE_IS_SUBSCRIBED)
disableMenu = bundle.getBoolean(BUNDLE_DISABLE_MENU)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = container?.inflate(R.layout.fragment_chat_details)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(this, factory).get(ChatDetailsViewModel::class.java)
setupOptions()
setupToolbar()
getDetails()
}
override fun displayDetails(room: ChatDetails) {
ui {
val text = room.name
name.text = text
bindImage(chatRoomType!!)
content_topic.text = if (room.topic.isNullOrEmpty()) getString(R.string.msg_no_topic) else room.topic
content_announcement.text = if (room.announcement.isNullOrEmpty()) getString(R.string.msg_no_announcement) else room.announcement
content_description.text = if (room.description.isNullOrEmpty()) getString(R.string.msg_no_description) else room.description
}
}
override fun showGenericErrorMessage() = showMessage(R.string.msg_generic_error)
override fun showMessage(resId: Int) {
ui {
showToast(resId)
}
}
override fun showMessage(message: String) {
ui {
showToast(message)
}
}
private fun addOptions(adapter: ChatDetailsAdapter?) {
adapter?.let {
if (!disableMenu) {
it.addOption(getString(R.string.title_files), R.drawable.ic_files_24dp) {
presenter.toFiles(chatRoomId!!)
}
}
if (chatRoomType != RoomType.DIRECT_MESSAGE && !disableMenu) {
it.addOption(getString(R.string.msg_mentions), R.drawable.ic_at_black_20dp) {
presenter.toMentions(chatRoomId!!)
}
it.addOption(getString(R.string.title_members), R.drawable.ic_people_outline_black_24dp) {
presenter.toMembers(chatRoomId!!)
}
}
it.addOption(getString(R.string.title_favorite_messages), R.drawable.ic_star_border_white_24dp) {
presenter.toFavorites(chatRoomId!!)
}
it.addOption(getString(R.string.title_pinned_messages), R.drawable.ic_action_message_pin_24dp) {
presenter.toPinned(chatRoomId!!)
}
}
}
private fun bindImage(chatRoomType: String) {
val drawable = when (roomTypeOf(chatRoomType)) {
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!!)
}
else -> null
}
drawable?.let {
val wrappedDrawable = DrawableHelper.wrapDrawable(it)
val mutableDrawable = wrappedDrawable.mutate()
DrawableHelper.tintDrawable(mutableDrawable, context!!, R.color.colorPrimary)
DrawableHelper.compoundDrawable(name, mutableDrawable)
}
}
private fun getDetails() {
if (isSubscribed)
viewModel.getDetails(chatRoomId!!).observe(viewLifecycleOwner, Observer { details ->
displayDetails(details)
})
else
presenter.getDetails(chatRoomId!!, chatRoomType!!)
}
private fun setupOptions() {
ui {
if (options.adapter == null) {
adapter = ChatDetailsAdapter()
options.adapter = adapter
with(options) {
layoutManager = LinearLayoutManager(it)
addItemDecoration(
DividerItemDecoration(
it,
resources.getDimensionPixelSize(R.dimen.divider_item_decorator_bound_start),
resources.getDimensionPixelSize(R.dimen.divider_item_decorator_bound_end)
)
)
itemAnimator = DefaultItemAnimator()
isNestedScrollingEnabled = false
}
}
addOptions(adapter)
}
}
private fun setupToolbar() {
(activity as ChatDetailsActivity).let {
it.setNavigationIcon(R.drawable.ic_close_white_24dp)
it.setToolbarTitle(getString(R.string.title_channel_details))
}
}
}
\ No newline at end of file
package chat.rocket.android.chatdetails.viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel
import chat.rocket.android.chatdetails.domain.ChatDetails
import chat.rocket.android.db.ChatRoomDao
class ChatDetailsViewModel(private val chatRoomDao: ChatRoomDao): ViewModel() {
fun getDetails(chatRoomId: String): LiveData<ChatDetails> {
return Transformations.switchMap(chatRoomDao.get(chatRoomId)) { room ->
val entity = room.chatRoom
val data: MutableLiveData<ChatDetails> = MutableLiveData()
data.value = ChatDetails(
entity.name,
entity.fullname,
entity.type,
entity.topic,
entity.announcement,
entity.description
)
return@switchMap data
}
}
}
\ No newline at end of file
package chat.rocket.android.chatdetails.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import chat.rocket.android.db.ChatRoomDao
import javax.inject.Inject
class ChatDetailsViewModelFactory @Inject constructor(private val chatRoomDao: ChatRoomDao) : ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>) =
ChatDetailsViewModel(chatRoomDao) as T
}
\ No newline at end of file
...@@ -251,6 +251,9 @@ class ChatRoomAdapter( ...@@ -251,6 +251,9 @@ class ChatRoomAdapter(
R.id.action_message_permalink -> { R.id.action_message_permalink -> {
actionSelectListener?.copyPermalink(id) actionSelectListener?.copyPermalink(id)
} }
R.id.action_message_report -> {
actionSelectListener?.reportMessage(id)
}
else -> { else -> {
TODO("Not implemented") TODO("Not implemented")
} }
...@@ -260,16 +263,29 @@ class ChatRoomAdapter( ...@@ -260,16 +263,29 @@ class ChatRoomAdapter(
} }
interface OnActionSelected { interface OnActionSelected {
fun showMessageInfo(id: String) fun showMessageInfo(id: String)
fun citeMessage(roomName: String, roomType: String, messageId: String, mentionAuthor: Boolean) fun citeMessage(roomName: String, roomType: String, messageId: String, mentionAuthor: Boolean)
fun copyMessage(id: String) fun copyMessage(id: String)
fun editMessage(roomId: String, messageId: String, text: String) fun editMessage(roomId: String, messageId: String, text: String)
fun toogleStar(id: String, star: Boolean) fun toogleStar(id: String, star: Boolean)
fun tooglePin(id: String, pin: Boolean) fun tooglePin(id: String, pin: Boolean)
fun deleteMessage(roomId: String, id: String) fun deleteMessage(roomId: String, id: String)
fun showReactions(id: String) fun showReactions(id: String)
fun openDirectMessage(roomName: String, message: String) fun openDirectMessage(roomName: String, message: String)
fun sendMessage(chatRoomId: String, text: String) fun sendMessage(chatRoomId: String, text: String)
fun copyPermalink(id: String) fun copyPermalink(id: String)
fun reportMessage(id: String)
} }
} }
package chat.rocket.android.chatroom.adapter package chat.rocket.android.chatroom.adapter
import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.text.Spannable import android.text.Spannable
...@@ -10,6 +11,7 @@ import androidx.core.view.isVisible ...@@ -10,6 +11,7 @@ import androidx.core.view.isVisible
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.uimodel.MessageUiModel import chat.rocket.android.chatroom.uimodel.MessageUiModel
import chat.rocket.android.emoji.EmojiReactionListener import chat.rocket.android.emoji.EmojiReactionListener
import chat.rocket.android.userdetails.ui.userDetailsIntent
import chat.rocket.core.model.isSystemMessage import chat.rocket.core.model.isSystemMessage
import com.bumptech.glide.load.resource.gif.GifDrawable import com.bumptech.glide.load.resource.gif.GifDrawable
import kotlinx.android.synthetic.main.avatar.view.* import kotlinx.android.synthetic.main.avatar.view.*
...@@ -70,9 +72,25 @@ class MessageViewHolder( ...@@ -70,9 +72,25 @@ class MessageViewHolder(
) )
read_receipt_view.isVisible = true read_receipt_view.isVisible = true
} }
val senderId = data.message.sender?.id
val subscriptionId = data.subscriptionId
text_sender.setOnClickListener {
toUserDetails(context, senderId, subscriptionId)
}
image_avatar.setOnClickListener {
toUserDetails(context, senderId, subscriptionId)
}
} }
} }
private fun toUserDetails(context: Context, userId: String?, subscriptionId: String) {
userId?.let { context.startActivity(context.userDetailsIntent(it, subscriptionId)) }
}
override fun unscheduleDrawable(who: Drawable?, what: Runnable?) { override fun unscheduleDrawable(who: Drawable?, what: Runnable?) {
with(itemView) { with(itemView) {
text_content.removeCallbacks(what) text_content.removeCallbacks(what)
......
...@@ -9,9 +9,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy ...@@ -9,9 +9,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.ChatRoomDao import chat.rocket.android.db.ChatRoomDao
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.db.UserDao import chat.rocket.android.db.UserDao
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetCurrentUserInteractor import chat.rocket.android.server.domain.GetCurrentUserInteractor
import chat.rocket.android.server.domain.PermissionsInteractor import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
......
package chat.rocket.android.chatroom.presentation package chat.rocket.android.chatroom.presentation
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatdetails.ui.chatDetailsIntent
import chat.rocket.android.chatinformation.ui.messageInformationIntent import chat.rocket.android.chatinformation.ui.messageInformationIntent
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatroom.ui.chatRoomIntent import chat.rocket.android.chatroom.ui.chatRoomIntent
...@@ -13,35 +14,20 @@ import chat.rocket.android.server.ui.changeServerIntent ...@@ -13,35 +14,20 @@ import chat.rocket.android.server.ui.changeServerIntent
import chat.rocket.android.util.extensions.addFragmentBackStack import chat.rocket.android.util.extensions.addFragmentBackStack
class ChatRoomNavigator(internal val activity: ChatRoomActivity) { class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
fun toChatDetails(
fun toMembersList(chatRoomId: String) { chatRoomId: String,
activity.addFragmentBackStack(TAG_MEMBERS_FRAGMENT, R.id.fragment_container) { chatRoomType: String,
chat.rocket.android.members.ui.newInstance(chatRoomId) isChatRoomSubscribed: Boolean,
} isMenuDisabled: Boolean
} ) {
activity.startActivity(
fun toMentions(chatRoomId: String) { activity.chatDetailsIntent(
activity.addFragmentBackStack(TAG_MENTIONS_FRAGMENT, R.id.fragment_container) { chatRoomId,
chat.rocket.android.mentions.ui.newInstance(chatRoomId) chatRoomType,
} isChatRoomSubscribed,
} isMenuDisabled
)
fun toPinnedMessageList(chatRoomId: String) { )
activity.addFragmentBackStack(TAG_PINNED_MESSAGES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.pinnedmessages.ui.newInstance(chatRoomId)
}
}
fun toFavoriteMessageList(chatRoomId: String) {
activity.addFragmentBackStack(TAG_FAVORITE_MESSAGES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.favoritemessages.ui.newInstance(chatRoomId)
}
}
fun toFileList(chatRoomId: String) {
activity.addFragmentBackStack(TAG_FILES_FRAGMENT, R.id.fragment_container) {
chat.rocket.android.files.ui.newInstance(chatRoomId)
}
} }
fun toNewServer() { fun toNewServer() {
...@@ -80,4 +66,4 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) { ...@@ -80,4 +66,4 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
activity.startActivity(activity.messageInformationIntent(messageId = messageId)) activity.startActivity(activity.messageInformationIntent(messageId = messageId))
activity.overridePendingTransition(R.anim.open_enter, R.anim.open_exit) activity.overridePendingTransition(R.anim.open_enter, R.anim.open_exit)
} }
} }
\ No newline at end of file
...@@ -38,7 +38,6 @@ import chat.rocket.android.server.infraestructure.state ...@@ -38,7 +38,6 @@ import chat.rocket.android.server.infraestructure.state
import chat.rocket.android.util.extension.getByteArray import chat.rocket.android.util.extension.getByteArray
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.exhaustive
import chat.rocket.android.util.retryDB import chat.rocket.android.util.retryDB
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
...@@ -61,6 +60,7 @@ import chat.rocket.core.internal.rest.joinChat ...@@ -61,6 +60,7 @@ import chat.rocket.core.internal.rest.joinChat
import chat.rocket.core.internal.rest.markAsRead import chat.rocket.core.internal.rest.markAsRead
import chat.rocket.core.internal.rest.messages import chat.rocket.core.internal.rest.messages
import chat.rocket.core.internal.rest.pinMessage import chat.rocket.core.internal.rest.pinMessage
import chat.rocket.core.internal.rest.reportMessage
import chat.rocket.core.internal.rest.runCommand import chat.rocket.core.internal.rest.runCommand
import chat.rocket.core.internal.rest.searchMessages import chat.rocket.core.internal.rest.searchMessages
import chat.rocket.core.internal.rest.sendMessage import chat.rocket.core.internal.rest.sendMessage
...@@ -374,6 +374,19 @@ class ChatRoomPresenter @Inject constructor( ...@@ -374,6 +374,19 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun reportMessage(messageId: String, description: String) {
launchUI(strategy) {
try {
retryIO("reportMessage($messageId, $description)") {
client.reportMessage(messageId = messageId, description = description)
}
view.showMessage(R.string.report_sent)
} catch (ex: RocketChatException) {
Timber.e(ex)
}
}
}
fun selectFile() { fun selectFile() {
view.showFileSelection(settings.uploadMimeTypeFilter()) view.showFileSelection(settings.uploadMimeTypeFilter())
} }
...@@ -887,20 +900,14 @@ class ChatRoomPresenter @Inject constructor( ...@@ -887,20 +900,14 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun toMembersList(chatRoomId: String) = fun toChatDetails(
navigator.toMembersList(chatRoomId) chatRoomId: String,
chatRoomType: String,
fun toMentions(chatRoomId: String) = isSubscribed: Boolean,
navigator.toMentions(chatRoomId) isMenuDisabled: Boolean
) {
fun toPinnedMessageList(chatRoomId: String) = navigator.toChatDetails(chatRoomId, chatRoomType, isSubscribed, isMenuDisabled)
navigator.toPinnedMessageList(chatRoomId) }
fun toFavoriteMessageList(chatRoomId: String) =
navigator.toFavoriteMessageList(chatRoomId)
fun toFileList(chatRoomId: String) =
navigator.toFileList(chatRoomId)
fun loadChatRooms() { fun loadChatRooms() {
launchUI(strategy) { launchUI(strategy) {
...@@ -929,7 +936,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -929,7 +936,7 @@ class ChatRoomPresenter @Inject constructor(
// TODO: move this to new interactor or FetchChatRoomsInteractor? // TODO: move this to new interactor or FetchChatRoomsInteractor?
private suspend fun getChatRoomAsync(roomId: String): ChatRoom? = withContext(CommonPool) { private suspend fun getChatRoomAsync(roomId: String): ChatRoom? = withContext(CommonPool) {
retryDB("getRoom($roomId)") { retryDB("getRoom($roomId)") {
dbManager.chatRoomDao().get(roomId)?.let { dbManager.chatRoomDao().getSync(roomId)?.let {
with(it.chatRoom) { with(it.chatRoom) {
ChatRoom( ChatRoom(
id = id, id = id,
......
...@@ -68,17 +68,18 @@ import chat.rocket.android.helper.ImageHelper ...@@ -68,17 +68,18 @@ import chat.rocket.android.helper.ImageHelper
import chat.rocket.android.helper.KeyboardHelper import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.MessageParser import chat.rocket.android.helper.MessageParser
import chat.rocket.android.util.extension.asObservable import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extension.createImageFile
import chat.rocket.android.util.extensions.circularRevealOrUnreveal import chat.rocket.android.util.extensions.circularRevealOrUnreveal
import chat.rocket.android.util.extensions.content
import chat.rocket.android.util.extensions.fadeIn import chat.rocket.android.util.extensions.fadeIn
import chat.rocket.android.util.extensions.fadeOut import chat.rocket.android.util.extensions.fadeOut
import chat.rocket.android.util.extensions.getBitmpap
import chat.rocket.android.util.extensions.hideKeyboard import chat.rocket.android.util.extensions.hideKeyboard
import chat.rocket.android.util.extensions.inflate import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.rotateBy import chat.rocket.android.util.extensions.rotateBy
import chat.rocket.android.util.extensions.showToast import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.extension.createImageFile
import chat.rocket.android.util.extensions.getBitmpap
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
import chat.rocket.core.internal.realtime.socket.model.State import chat.rocket.core.internal.realtime.socket.model.State
...@@ -86,16 +87,16 @@ import dagger.android.support.AndroidSupportInjection ...@@ -86,16 +87,16 @@ import dagger.android.support.AndroidSupportInjection
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.emoji_image_row_item.* import kotlinx.android.synthetic.main.emoji_image_row_item.view.*
import kotlinx.android.synthetic.main.emoji_row_item.* import kotlinx.android.synthetic.main.emoji_row_item.view.*
import kotlinx.android.synthetic.main.fragment_chat_room.* import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_attachment_options.* import kotlinx.android.synthetic.main.message_attachment_options.*
import kotlinx.android.synthetic.main.message_composer.* import kotlinx.android.synthetic.main.message_composer.*
import kotlinx.android.synthetic.main.message_list.* import kotlinx.android.synthetic.main.message_list.*
import kotlinx.android.synthetic.main.reaction_praises_list_item.view.*
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import kotlinx.android.synthetic.main.reaction_praises_list_item.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject import javax.inject.Inject
...@@ -141,12 +142,8 @@ private const val BUNDLE_CHAT_ROOM_IS_CREATOR = "chat_room_is_creator" ...@@ -141,12 +142,8 @@ private const val BUNDLE_CHAT_ROOM_IS_CREATOR = "chat_room_is_creator"
private const val BUNDLE_CHAT_ROOM_IS_FAVORITE = "chat_room_is_favorite" private const val BUNDLE_CHAT_ROOM_IS_FAVORITE = "chat_room_is_favorite"
private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message" private const val BUNDLE_CHAT_ROOM_MESSAGE = "chat_room_message"
internal const val MENU_ACTION_FAVORITE_UNFAVORITE_CHAT = 1 internal const val MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT = 1
internal const val MENU_ACTION_MEMBER = 2 internal const val MENU_ACTION_SHOW_DETAILS = 2
internal const val MENU_ACTION_MENTIONS = 3
internal const val MENU_ACTION_PINNED_MESSAGES = 4
internal const val MENU_ACTION_FAVORITE_MESSAGES = 5
internal const val MENU_ACTION_FILES = 6
class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener, class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiReactionListener,
ChatRoomAdapter.OnActionSelected, Drawable.Callback { ChatRoomAdapter.OnActionSelected, Drawable.Callback {
...@@ -163,7 +160,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -163,7 +160,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
internal lateinit var chatRoomType: String internal lateinit var chatRoomType: String
private var newMessageCount: Int = 0 private var newMessageCount: Int = 0
private var chatRoomMessage: String? = null private var chatRoomMessage: String? = null
private var isSubscribed: Boolean = true internal var isSubscribed: Boolean = true
private var isReadOnly: Boolean = false private var isReadOnly: Boolean = false
private var isCreator: Boolean = false private var isCreator: Boolean = false
internal var isFavorite: Boolean = false internal var isFavorite: Boolean = false
...@@ -704,9 +701,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -704,9 +701,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
GlideApp.with(requireContext()).asBitmap() GlideApp.with(requireContext()).asBitmap()
} }
glideRequest.load(url).into(emoji_image_view) glideRequest.load(url).into(view_flipper.emoji_image_view)
} else { } else {
emoji_view.text = EmojiParser.parse(requireContext(), shortname) view_flipper.emoji_view.text = EmojiParser.parse(requireContext(), shortname)
} }
var listing = "" var listing = ""
...@@ -843,9 +840,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -843,9 +840,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} else { } else {
input_container.isVisible = true input_container.isVisible = true
text_room_is_read_only.isVisible = false text_room_is_read_only.isVisible = false
button_send.isVisible = false
button_show_attachment_options.alpha = 1f button_show_attachment_options.alpha = 1f
button_show_attachment_options.isVisible = true
activity?.supportFragmentManager?.registerFragmentLifecycleCallbacks( activity?.supportFragmentManager?.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() { object : FragmentManager.FragmentLifecycleCallbacks() {
...@@ -863,7 +858,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -863,7 +858,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
) )
subscribeComposeTextMessage() subscribeComposeTextMessage()
getUnfinishedMessage()
emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container)) emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container))
emojiKeyboardPopup.listener = this emojiKeyboardPopup.listener = this
text_message.listener = object : ComposerEditText.ComposerEditTextListener { text_message.listener = object : ComposerEditText.ComposerEditTextListener {
...@@ -1173,4 +1167,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -1173,4 +1167,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override fun sendMessage(chatRoomId: String, text: String) { override fun sendMessage(chatRoomId: String, text: String) {
presenter.sendMessage(chatRoomId, text, null) presenter.sendMessage(chatRoomId, text, null)
} }
override fun reportMessage(id: String) {
presenter.reportMessage(messageId = id,
description = "This message was reported by a user from the Android app")
}
} }
...@@ -8,63 +8,25 @@ import androidx.appcompat.widget.SearchView ...@@ -8,63 +8,25 @@ import androidx.appcompat.widget.SearchView
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.util.extension.onQueryTextListener import chat.rocket.android.util.extension.onQueryTextListener
import chat.rocket.common.model.RoomType
internal fun ChatRoomFragment.setupMenu(menu: Menu) { internal fun ChatRoomFragment.setupMenu(menu: Menu) {
setupSearchMessageMenuItem(menu, requireContext()) setupSearchMessageMenuItem(menu, requireContext())
setupFavoriteMenuItem(menu) setupFavoriteMenuItem(menu)
setupDetailsMenuItem(menu)
menu.add(
Menu.NONE,
MENU_ACTION_PINNED_MESSAGES,
Menu.NONE,
R.string.title_pinned_messages
)
menu.add(
Menu.NONE,
MENU_ACTION_FAVORITE_MESSAGES,
Menu.NONE,
R.string.title_favorite_messages
)
if (chatRoomType != RoomType.DIRECT_MESSAGE && !disableMenu) {
menu.add(
Menu.NONE,
MENU_ACTION_MEMBER,
Menu.NONE,
R.string.title_members_list
)
menu.add(
Menu.NONE,
MENU_ACTION_MENTIONS,
Menu.NONE,
R.string.msg_mentions
)
}
if (!disableMenu) {
menu.add(
Menu.NONE,
MENU_ACTION_FILES,
Menu.NONE,
R.string.title_files
)
}
} }
internal fun ChatRoomFragment.setOnMenuItemClickListener(item: MenuItem) { internal fun ChatRoomFragment.setOnMenuItemClickListener(item: MenuItem) {
when (item.itemId) { when (item.itemId) {
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT -> presenter.toggleFavoriteChatRoom( MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT -> presenter.toggleFavoriteChatRoom(
chatRoomId, chatRoomId,
isFavorite isFavorite
) )
MENU_ACTION_MEMBER -> presenter.toMembersList(chatRoomId) MENU_ACTION_SHOW_DETAILS -> presenter.toChatDetails(
MENU_ACTION_MENTIONS -> presenter.toMentions(chatRoomId) chatRoomId,
MENU_ACTION_PINNED_MESSAGES -> presenter.toPinnedMessageList(chatRoomId) chatRoomType,
MENU_ACTION_FAVORITE_MESSAGES -> presenter.toFavoriteMessageList(chatRoomId) isSubscribed,
MENU_ACTION_FILES -> presenter.toFileList(chatRoomId) disableMenu
)
} }
} }
...@@ -125,7 +87,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) { ...@@ -125,7 +87,7 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) {
if (isFavorite) { if (isFavorite) {
menu.add( menu.add(
Menu.NONE, Menu.NONE,
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT, MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT,
Menu.NONE, Menu.NONE,
R.string.title_unfavorite_chat R.string.title_unfavorite_chat
).setIcon(R.drawable.ic_star_yellow_24dp) ).setIcon(R.drawable.ic_star_yellow_24dp)
...@@ -133,10 +95,20 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) { ...@@ -133,10 +95,20 @@ private fun ChatRoomFragment.setupFavoriteMenuItem(menu: Menu) {
} else { } else {
menu.add( menu.add(
Menu.NONE, Menu.NONE,
MENU_ACTION_FAVORITE_UNFAVORITE_CHAT, MENU_ACTION_FAVORITE_UNFAVOURITE_CHAT,
Menu.NONE, Menu.NONE,
R.string.title_favorite_chat R.string.title_favorite_chat
).setIcon(R.drawable.ic_star_border_white_24dp) ).setIcon(R.drawable.ic_star_border_white_24dp)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
} }
}
private fun ChatRoomFragment.setupDetailsMenuItem(menu: Menu) {
menu.add(
Menu.NONE,
MENU_ACTION_SHOW_DETAILS,
Menu.NONE,
"Channel Details"
).setIcon(R.drawable.ic_info_outline_white_24dp)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
} }
\ No newline at end of file
...@@ -21,7 +21,8 @@ data class MessageUiModel( ...@@ -21,7 +21,8 @@ data class MessageUiModel(
var isFirstUnread: Boolean, var isFirstUnread: Boolean,
override var isTemporary: Boolean = false, override var isTemporary: Boolean = false,
override var menuItemsToHide: MutableList<Int> = mutableListOf(), override var menuItemsToHide: MutableList<Int> = mutableListOf(),
override var permalink: String override var permalink: String,
val subscriptionId: String
) : BaseMessageUiModel<Message> { ) : BaseMessageUiModel<Message> {
override val viewType: Int override val viewType: Int
get() = BaseUiModel.ViewType.MESSAGE.viewType get() = BaseUiModel.ViewType.MESSAGE.viewType
......
...@@ -164,7 +164,7 @@ class UiModelMapper @Inject constructor( ...@@ -164,7 +164,7 @@ class UiModelMapper @Inject constructor(
// TODO: move this to new interactor or FetchChatRoomsInteractor? // TODO: move this to new interactor or FetchChatRoomsInteractor?
private suspend fun getChatRoomAsync(roomId: String): ChatRoom? = withContext(CommonPool) { private suspend fun getChatRoomAsync(roomId: String): ChatRoom? = withContext(CommonPool) {
return@withContext dbManager.chatRoomDao().get(roomId)?.let { return@withContext dbManager.chatRoomDao().getSync(roomId)?.let {
with(it.chatRoom) { with(it.chatRoom) {
ChatRoom( ChatRoom(
id = id, id = id,
...@@ -456,7 +456,8 @@ class UiModelMapper @Inject constructor( ...@@ -456,7 +456,8 @@ class UiModelMapper @Inject constructor(
messageId = message.id, avatar = avatar!!, time = time, senderName = sender, messageId = message.id, avatar = avatar!!, time = time, senderName = sender,
content = content, isPinned = message.pinned, currentDayMarkerText = dayMarkerText, content = content, isPinned = message.pinned, currentDayMarkerText = dayMarkerText,
showDayMarker = false, reactions = getReactions(message), isFirstUnread = false, showDayMarker = false, reactions = getReactions(message), isFirstUnread = false,
preview = preview, isTemporary = !synced, unread = unread, permalink = permalink) preview = preview, isTemporary = !synced, unread = unread, permalink = permalink,
subscriptionId = chatRoom.subscriptionId)
} }
private fun mapMessagePreview(message: Message): Message { private fun mapMessagePreview(message: Message): Message {
......
...@@ -2,9 +2,6 @@ package chat.rocket.android.chatrooms.adapter ...@@ -2,9 +2,6 @@ package chat.rocket.android.chatrooms.adapter
import android.app.Application import android.app.Application
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import androidx.core.content.ContextCompat
import androidx.core.text.bold
import androidx.core.text.color
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.model.RoomUiModel import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import chat.rocket.android.db.model.ChatRoom import chat.rocket.android.db.model.ChatRoom
...@@ -32,18 +29,13 @@ class RoomUiModelMapper( ...@@ -32,18 +29,13 @@ class RoomUiModelMapper(
private val serverUrl: String, private val serverUrl: String,
private val permissions: PermissionsInteractor private val permissions: PermissionsInteractor
) { ) {
private val nameUnreadColor = ContextCompat.getColor(context, R.color.colorPrimaryText) private val currentUser by lazy { userInteractor.get() }
private val nameColor = ContextCompat.getColor(context, R.color.colorSecondaryText)
private val dateUnreadColor = ContextCompat.getColor(context, R.color.colorAccent)
private val dateColor = ContextCompat.getColor(context, R.color.colorSecondaryText)
private val messageUnreadColor = ContextCompat.getColor(context, android.R.color.primary_text_light)
private val messageColor = ContextCompat.getColor(context, R.color.colorSecondaryText)
private val currentUser by lazy {
userInteractor.get()
}
fun map(rooms: List<ChatRoom>, grouped: Boolean = false, showLastMessage: Boolean = true): List<ItemHolder<*>> { fun map(
rooms: List<ChatRoom>,
grouped: Boolean = false,
showLastMessage: Boolean = true
): List<ItemHolder<*>> {
val list = ArrayList<ItemHolder<*>>(rooms.size + 4) val list = ArrayList<ItemHolder<*>>(rooms.size + 4)
var lastType: String? = null var lastType: String? = null
rooms.forEach { room -> rooms.forEach { room ->
...@@ -72,7 +64,7 @@ class RoomUiModelMapper( ...@@ -72,7 +64,7 @@ class RoomUiModelMapper(
private fun mapUser(user: User): RoomUiModel { private fun mapUser(user: User): RoomUiModel {
return with(user) { return with(user) {
val name = mapName(user.username!!, user.name, false) val name = mapName(user.username!!, user.name)
val status = user.status val status = user.status
val avatar = serverUrl.avatarUrl(user.username!!) val avatar = serverUrl.avatarUrl(user.username!!)
val username = user.username!! val username = user.username!!
...@@ -88,41 +80,56 @@ class RoomUiModelMapper( ...@@ -88,41 +80,56 @@ class RoomUiModelMapper(
} }
} }
private fun mapRoom(room: Room, showLastMessage:Boolean = true): RoomUiModel { private fun mapRoom(room: Room, showLastMessage: Boolean = true): RoomUiModel {
return with(room) { return with(room) {
RoomUiModel( RoomUiModel(
id = id, id = id,
name = name!!, name = name!!,
type = type, type = type,
avatar = serverUrl.avatarUrl(name!!, isGroupOrChannel = true), avatar = serverUrl.avatarUrl(name!!, isGroupOrChannel = true),
lastMessage = if(showLastMessage) { mapLastMessage(lastMessage?.sender?.id, lastMessage?.sender?.username, lastMessage = if (showLastMessage) {
mapLastMessage(
lastMessage?.sender?.id, lastMessage?.sender?.username,
lastMessage?.sender?.name, lastMessage?.message, lastMessage?.sender?.name, lastMessage?.message,
isDirectMessage = type is RoomType.DirectMessage)} else { null }, isDirectMessage = type is RoomType.DirectMessage
)
} else {
null
},
muted = muted.orEmpty(), muted = muted.orEmpty(),
writable = isChannelWritable(muted) writable = isChannelWritable(muted)
) )
} }
} }
fun map(chatRoom: ChatRoom, showLastMessage:Boolean = true): RoomUiModel { fun map(chatRoom: ChatRoom, showLastMessage: Boolean = true): RoomUiModel {
return with(chatRoom.chatRoom) { return with(chatRoom.chatRoom) {
val isUnread = alert || unread > 0 val isUnread = alert || unread > 0
val type = roomTypeOf(type) val type = roomTypeOf(type)
val status = chatRoom.status?.let { userStatusOf(it) } val status = chatRoom.status?.let { userStatusOf(it) }
val roomName = mapName(name, fullname, isUnread) val roomName = mapName(name, fullname)
val timestamp = mapDate(lastMessageTimestamp ?: updatedAt, isUnread) val timestamp = mapDate(lastMessageTimestamp ?: updatedAt)
val avatar = if (type is RoomType.DirectMessage) { val avatar = if (type is RoomType.DirectMessage) {
serverUrl.avatarUrl(name) serverUrl.avatarUrl(name)
} else { } else {
serverUrl.avatarUrl(name, isGroupOrChannel = true) serverUrl.avatarUrl(name, isGroupOrChannel = true)
} }
val unread = mapUnread(unread) val unread = mapUnread(unread)
val lastMessage = if(showLastMessage) { mapLastMessage(lastMessageUserId, chatRoom.lastMessageUserName, val lastMessage = if (showLastMessage) {
chatRoom.lastMessageUserFullName, lastMessageText, isUnread, mapLastMessage(
type is RoomType.DirectMessage) } else { null } lastMessageUserId,
chatRoom.lastMessageUserName,
chatRoom.lastMessageUserFullName,
lastMessageText,
type is RoomType.DirectMessage
)
} else {
null
}
val hasMentions = mapMentions(userMentions, groupMentions)
val open = open val open = open
val lastMessageMarkdown =
val lastMessageMarkdown = lastMessage?.let { Markwon.markdown(context, it.toString()).toString() } lastMessage?.let { Markwon.markdown(context, it.toString()).toString() }
RoomUiModel( RoomUiModel(
id = id, id = id,
...@@ -132,6 +139,7 @@ class RoomUiModelMapper( ...@@ -132,6 +139,7 @@ class RoomUiModelMapper(
open = open, open = open,
date = timestamp, date = timestamp,
unread = unread, unread = unread,
mentions = hasMentions,
alert = isUnread, alert = isUnread,
lastMessage = lastMessageMarkdown, lastMessage = lastMessageMarkdown,
status = status, status = status,
...@@ -158,47 +166,37 @@ class RoomUiModelMapper( ...@@ -158,47 +166,37 @@ class RoomUiModelMapper(
} }
} }
private fun mapLastMessage(userId: String?, name: String?, fullName: String?, text: String?, private fun mapLastMessage(
unread: Boolean = false, userId: String?,
isDirectMessage: Boolean = false): CharSequence? { name: String?,
fullName: String?,
text: String?,
isDirectMessage: Boolean = false
): CharSequence? {
return if (!settings.showLastMessage()) { return if (!settings.showLastMessage()) {
null null
} else if (name != null && text != null) { } else if (name != null && text != null) {
val user = if (currentUser != null && currentUser!!.id == userId) { val user = if (currentUser != null && currentUser!!.id == userId) {
"${context.getString(R.string.msg_you)}: " "${context.getString(R.string.msg_you)}: "
} else { } else {
if (isDirectMessage) "" else "${mapName(name, fullName, unread)}: " if (isDirectMessage) "" else "${mapName(name, fullName)}: "
} }
SpannableStringBuilder().append(user).append(text)
val color = if (unread) messageUnreadColor else messageColor
SpannableStringBuilder()
.color(color) {
bold { append(user) }
append(text)
}
} else { } else {
context.getText(R.string.msg_no_messages_yet) context.getText(R.string.msg_no_messages_yet)
} }
} }
private fun mapName(name: String, fullName: String?, unread: Boolean): CharSequence { private fun mapName(name: String, fullName: String?): CharSequence {
val roomName = if (settings.useSpecialCharsOnRoom() || settings.useRealName()) { return if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
fullName ?: name fullName ?: name
} else { } else {
name name
} }
val color = if (unread) nameUnreadColor else nameColor
return SpannableStringBuilder()
.color(color) {
append(roomName)
}
} }
private fun mapUnread(unread: Long): String? { private fun mapUnread(unread: Long): String? {
return when(unread) { return when (unread) {
0L -> null 0L -> null
in 1..99 -> unread.toString() in 1..99 -> unread.toString()
else -> context.getString(R.string.msg_more_than_ninety_nine_unread_messages) else -> context.getString(R.string.msg_more_than_ninety_nine_unread_messages)
...@@ -206,12 +204,14 @@ class RoomUiModelMapper( ...@@ -206,12 +204,14 @@ class RoomUiModelMapper(
} }
} }
private fun mapDate(date: Long?, unread: Boolean): CharSequence? { private fun mapMentions(userMentions: Long?, groupMentions: Long?): Boolean {
return date?.localDateTime()?.date(context)?.let { if (userMentions != null && groupMentions != null) {
val color = if (unread) dateUnreadColor else dateColor if (userMentions > 0 || groupMentions > 0) {
SpannableStringBuilder().color(color) { return true
append(it)
} }
} }
return false
} }
private fun mapDate(date: Long?): CharSequence? = date?.localDateTime()?.date(context)
} }
...@@ -4,6 +4,7 @@ import android.content.res.Resources ...@@ -4,6 +4,7 @@ import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.View import android.view.View
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.model.RoomUiModel import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
...@@ -11,19 +12,16 @@ import chat.rocket.common.model.RoomType ...@@ -11,19 +12,16 @@ import chat.rocket.common.model.RoomType
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import kotlinx.android.synthetic.main.item_chat.view.* import kotlinx.android.synthetic.main.item_chat.view.*
import kotlinx.android.synthetic.main.unread_messages_badge.view.* import kotlinx.android.synthetic.main.unread_messages_badge.view.*
import ru.noties.markwon.Markwon
class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit) : ViewHolder<RoomItemHolder>(itemView) {
class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit) :
ViewHolder<RoomItemHolder>(itemView) {
private val resources: Resources = itemView.resources private val resources: Resources = itemView.resources
private val channelUnread: Drawable = resources.getDrawable(R.drawable.ic_hashtag_black_12dp) private val channelIcon: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp)
private val channel: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp) private val groupIcon: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp)
private val groupUnread: Drawable = resources.getDrawable(R.drawable.ic_lock_black_12_dp) private val onlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp)
private val group: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp) private val awayIcon: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp)
private val online: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp) private val busyIcon: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp)
private val away: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp) private val offlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp)
private val busy: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp)
private val offline: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp)
override fun bindViews(data: RoomItemHolder) { override fun bindViews(data: RoomItemHolder) {
val room = data.data val room = data.data
...@@ -31,53 +29,59 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit ...@@ -31,53 +29,59 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit
image_avatar.setImageURI(room.avatar) image_avatar.setImageURI(room.avatar)
text_chat_name.text = room.name text_chat_name.text = room.name
if (room.status != null && room.type is RoomType.DirectMessage) {
image_chat_icon.setImageDrawable(getStatusDrawable(room.status))
} else {
image_chat_icon.setImageDrawable(getRoomDrawable(room.type))
}
if (room.lastMessage != null) { if (room.lastMessage != null) {
text_last_message.isVisible = true
text_last_message.text = room.lastMessage text_last_message.text = room.lastMessage
text_last_message.isVisible = true
} else { } else {
text_last_message.isGone = true text_last_message.isGone = true
} }
if (room.date != null) { if (room.date != null) {
text_last_message_date_time.isVisible = true text_timestamp.text = room.date
text_last_message_date_time.text = room.date text_timestamp.isVisible = true
} else { } else {
text_last_message_date_time.isGone = true text_timestamp.isInvisible = true
} }
if (room.unread != null) { if (room.alert) {
if (room.unread == null) text_total_unread_messages.text = "!"
if (room.unread != null) text_total_unread_messages.text = room.unread
if (room.mentions) text_total_unread_messages.text = "@${room.unread}"
text_chat_name.setTextAppearance(context, R.style.ChatList_ChatName_Unread_TextView)
text_timestamp.setTextAppearance(context, R.style.ChatList_Timestamp_Unread_TextView)
text_last_message.setTextAppearance(context, R.style.ChatList_LastMessage_Unread_TextView)
text_total_unread_messages.isVisible = true text_total_unread_messages.isVisible = true
text_total_unread_messages.text = room.unread
} else { } else {
text_total_unread_messages.isGone = true text_chat_name.setTextAppearance(context, R.style.ChatList_ChatName_TextView)
text_timestamp.setTextAppearance(context, R.style.ChatList_Timestamp_TextView)
text_last_message.setTextAppearance(context, R.style.ChatList_LastMessage_TextView)
text_total_unread_messages.isInvisible = true
} }
if (room.status != null && room.type is RoomType.DirectMessage) { setOnClickListener { listener(room) }
image_chat_icon.setImageDrawable(getStatusDrawable(room.status))
} else {
image_chat_icon.setImageDrawable(getRoomDrawable(room.type, room.alert))
}
setOnClickListener {
listener(room)
}
} }
} }
private fun getRoomDrawable(type: RoomType, alert: Boolean): Drawable? { private fun getRoomDrawable(type: RoomType): Drawable? {
return when(type) { return when (type) {
is RoomType.Channel -> if (alert) channelUnread else channel is RoomType.Channel -> channelIcon
is RoomType.PrivateGroup -> if (alert) groupUnread else group is RoomType.PrivateGroup -> groupIcon
else -> null else -> null
} }
} }
private fun getStatusDrawable(status: UserStatus): Drawable { private fun getStatusDrawable(status: UserStatus): Drawable {
return when(status) { return when (status) {
is UserStatus.Online -> online is UserStatus.Online -> onlineIcon
is UserStatus.Away -> away is UserStatus.Away -> awayIcon
is UserStatus.Busy -> busy is UserStatus.Busy -> busyIcon
else -> offline else -> offlineIcon
} }
} }
} }
\ No newline at end of file
...@@ -6,7 +6,8 @@ import chat.rocket.android.R ...@@ -6,7 +6,8 @@ import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.model.RoomUiModel import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import chat.rocket.android.util.extensions.inflate import chat.rocket.android.util.extensions.inflate
class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : RecyclerView.Adapter<ViewHolder<*>>() { class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) :
RecyclerView.Adapter<ViewHolder<*>>() {
init { init {
setHasStableIds(true) setHasStableIds(true)
...@@ -40,16 +41,16 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : RecyclerView.A ...@@ -40,16 +41,16 @@ class RoomsAdapter(private val listener: (RoomUiModel) -> Unit) : RecyclerView.A
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
val item = values[position] val item = values[position]
return when(item) { return when (item) {
is HeaderItemHolder -> item.data.hashCode().toLong()
is RoomItemHolder -> item.data.id.hashCode().toLong() is RoomItemHolder -> item.data.id.hashCode().toLong()
is HeaderItemHolder -> item.data.hashCode().toLong()
is LoadingItemHolder -> "loading".hashCode().toLong() is LoadingItemHolder -> "loading".hashCode().toLong()
else -> throw IllegalStateException("View type must be either Room, Header or Loading") else -> throw IllegalStateException("View type must be either Room, Header or Loading")
} }
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return when(values[position]) { return when (values[position]) {
is RoomItemHolder -> VIEW_TYPE_ROOM is RoomItemHolder -> VIEW_TYPE_ROOM
is HeaderItemHolder -> VIEW_TYPE_HEADER is HeaderItemHolder -> VIEW_TYPE_HEADER
is LoadingItemHolder -> VIEW_TYPE_LOADING is LoadingItemHolder -> VIEW_TYPE_LOADING
......
...@@ -12,6 +12,7 @@ data class RoomUiModel( ...@@ -12,6 +12,7 @@ data class RoomUiModel(
val date: CharSequence? = null, val date: CharSequence? = null,
val unread: String? = null, val unread: String? = null,
val alert: Boolean = false, val alert: Boolean = false,
val mentions: Boolean = false,
val lastMessage: CharSequence? = null, val lastMessage: CharSequence? = null,
val status: UserStatus? = null, val status: UserStatus? = null,
val username: String? = null, val username: String? = null,
......
package chat.rocket.android.chatrooms.ui
import DateTimeHelper
import DrawableHelper
import android.content.Context
import android.graphics.Color
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import chat.rocket.android.R
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.checkIfMyself
import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.util.extensions.*
import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom
import com.facebook.drawee.view.SimpleDraweeView
import kotlinx.android.synthetic.main.item_chat.view.*
import kotlinx.android.synthetic.main.unread_messages_badge.view.*
class ChatRoomsAdapter(
private val context: Context,
private val settings: PublicSettings,
private val localRepository: LocalRepository,
private val listener: (ChatRoom) -> Unit
) : RecyclerView.Adapter<ChatRoomsAdapter.ViewHolder>() {
var dataSet: MutableList<ChatRoom> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(parent.inflate(R.layout.item_chat))
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(dataSet[position])
override fun getItemCount(): Int = dataSet.size
fun updateRooms(newRooms: List<ChatRoom>) {
dataSet.clear()
dataSet.addAll(newRooms)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(chatRoom: ChatRoom) = with(itemView) {
bindAvatar(chatRoom, image_avatar)
bindName(chatRoom, text_chat_name)
bindIcon(chatRoom, image_chat_icon)
if (settings.showLastMessage()) {
text_last_message.isVisible = true
text_last_message_date_time.isVisible = true
bindLastMessageDateTime(chatRoom, text_last_message_date_time)
bindLastMessage(chatRoom, text_last_message)
} else {
text_last_message.isVisible = false
text_last_message_date_time.isVisible = false
}
bindUnreadMessages(chatRoom, text_total_unread_messages)
if (chatRoom.alert || chatRoom.unread > 0) {
text_chat_name.setTextColor(ContextCompat.getColor(context,
R.color.colorPrimaryText))
text_last_message_date_time.setTextColor(ContextCompat.getColor(context,
R.color.colorAccent))
text_last_message.setTextColor(ContextCompat.getColor(context,
android.R.color.primary_text_light))
} else {
text_chat_name.setTextColor(ContextCompat.getColor(context,
R.color.colorSecondaryText))
text_last_message_date_time.setTextColor(ContextCompat.getColor(context,
R.color.colorSecondaryText))
text_last_message.setTextColor(ContextCompat.getColor(context,
R.color.colorSecondaryText))
}
setOnClickListener { listener(chatRoom) }
}
private fun bindAvatar(chatRoom: ChatRoom, drawee: SimpleDraweeView) {
if (chatRoom.type is RoomType.DirectMessage) {
drawee.setImageURI(chatRoom.client.url.avatarUrl(chatRoom.name))
} else {
drawee.setImageURI(chatRoom.client.url.avatarUrl(chatRoom.name, true))
}
}
private fun bindIcon(chatRoom: ChatRoom, imageView: ImageView) {
val drawable = when (chatRoom.type) {
is RoomType.Channel -> DrawableHelper.getDrawableFromId(
R.drawable.ic_hashtag_black_12dp,
context
)
is RoomType.PrivateGroup -> DrawableHelper.getDrawableFromId(
R.drawable.ic_lock_black_12_dp,
context
)
is RoomType.DirectMessage -> DrawableHelper.getUserStatusDrawable(
chatRoom.status,
context
)
else -> null
}
drawable?.let {
val mutateDrawable = DrawableHelper.wrapDrawable(it).mutate()
if (chatRoom.type !is RoomType.DirectMessage) {
val color = when (chatRoom.alert || chatRoom.unread > 0) {
true -> R.color.colorPrimaryText
false -> R.color.colorSecondaryText
}
DrawableHelper.tintDrawable(mutateDrawable, context, color)
}
imageView.setImageDrawable(mutateDrawable)
}
}
private fun bindName(chatRoom: ChatRoom, textView: TextView) {
textView.textContent = chatRoomName(chatRoom)
}
private fun chatRoomName(chatRoom: ChatRoom): String {
return if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
chatRoom.fullName ?: chatRoom.name
} else {
chatRoom.name
}
}
private fun bindLastMessageDateTime(chatRoom: ChatRoom, textView: TextView) {
val lastMessage = chatRoom.lastMessage
if (lastMessage != null) {
val localDateTime = DateTimeHelper.getLocalDateTime(lastMessage.timestamp)
textView.content = DateTimeHelper.getDate(localDateTime, context)
} else {
textView.content = ""
}
}
private fun bindLastMessage(chatRoom: ChatRoom, textView: TextView) {
val lastMessage = chatRoom.lastMessage
val lastMessageSender = lastMessage?.sender
if (lastMessage != null && lastMessageSender != null) {
val message = lastMessage.message
val senderUsername = if (settings.useRealName()) {
lastMessageSender.name ?: lastMessageSender.username
} else {
lastMessageSender.username
}
when (senderUsername) {
chatRoom.name -> {
textView.content = message
}
else -> {
val user = if (localRepository.checkIfMyself(lastMessageSender.username!!)) {
"${context.getString(R.string.msg_you)}: "
} else {
"$senderUsername: "
}
val spannable = SpannableStringBuilder(user)
val len = spannable.length
spannable.setSpan(ForegroundColorSpan(Color.BLACK), 0, len - 1, 0)
spannable.append(message)
textView.content = spannable
}
}
} else {
textView.content = context.getText(R.string.msg_no_messages_yet)
}
}
private fun bindUnreadMessages(chatRoom: ChatRoom, textView: TextView) {
val totalUnreadMessage = chatRoom.unread
when {
totalUnreadMessage in 1..99 -> {
textView.textContent = totalUnreadMessage.toString()
textView.isVisible = true
}
totalUnreadMessage > 99 -> {
textView.textContent = context.getString(R.string.msg_more_than_ninety_nine_unread_messages)
textView.isVisible = true
}
else -> textView.isVisible = false
}
}
}
}
\ No newline at end of file
...@@ -36,6 +36,8 @@ import chat.rocket.android.helper.SharedPreferenceHelper ...@@ -36,6 +36,8 @@ import chat.rocket.android.helper.SharedPreferenceHelper
import chat.rocket.android.util.extension.onQueryTextListener import chat.rocket.android.util.extension.onQueryTextListener
import chat.rocket.android.util.extensions.fadeIn import chat.rocket.android.util.extensions.fadeIn
import chat.rocket.android.util.extensions.fadeOut import chat.rocket.android.util.extensions.fadeOut
import chat.rocket.android.util.extensions.ifNotNullNorEmpty
import chat.rocket.android.util.extensions.ifNotNullNotEmpty
import chat.rocket.android.util.extensions.inflate import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui import chat.rocket.android.util.extensions.ui
...@@ -83,8 +85,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -83,8 +85,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
val bundle = arguments val bundle = arguments
if (bundle != null) { if (bundle != null) {
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID) chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID)
chatRoomId?.let { chatRoomId.ifNotNullNotEmpty { roomId ->
presenter.loadChatRoom(it) presenter.loadChatRoom(roomId)
chatRoomId = null chatRoomId = null
} }
} }
......
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
}
}
...@@ -11,6 +11,9 @@ import chat.rocket.android.authentication.server.di.ServerFragmentProvider ...@@ -11,6 +11,9 @@ import chat.rocket.android.authentication.server.di.ServerFragmentProvider
import chat.rocket.android.authentication.signup.di.SignupFragmentProvider import chat.rocket.android.authentication.signup.di.SignupFragmentProvider
import chat.rocket.android.authentication.twofactor.di.TwoFAFragmentProvider import chat.rocket.android.authentication.twofactor.di.TwoFAFragmentProvider
import chat.rocket.android.authentication.ui.AuthenticationActivity import chat.rocket.android.authentication.ui.AuthenticationActivity
import chat.rocket.android.chatdetails.di.ChatDetailsFragmentProvider
import chat.rocket.android.chatdetails.di.ChatDetailsModule
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.chatinformation.di.MessageInfoFragmentProvider import chat.rocket.android.chatinformation.di.MessageInfoFragmentProvider
import chat.rocket.android.chatinformation.ui.MessageInfoActivity import chat.rocket.android.chatinformation.ui.MessageInfoActivity
import chat.rocket.android.chatroom.di.ChatRoomFragmentProvider import chat.rocket.android.chatroom.di.ChatRoomFragmentProvider
...@@ -35,25 +38,26 @@ import chat.rocket.android.server.ui.ChangeServerActivity ...@@ -35,25 +38,26 @@ import chat.rocket.android.server.ui.ChangeServerActivity
import chat.rocket.android.settings.di.SettingsFragmentProvider import chat.rocket.android.settings.di.SettingsFragmentProvider
import chat.rocket.android.settings.password.di.PasswordFragmentProvider import chat.rocket.android.settings.password.di.PasswordFragmentProvider
import chat.rocket.android.settings.password.ui.PasswordActivity import chat.rocket.android.settings.password.ui.PasswordActivity
import chat.rocket.android.userdetails.di.UserDetailsModule
import chat.rocket.android.userdetails.ui.UserDetailsActivity
import chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider import chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
@Module @Module
abstract class ActivityBuilder { abstract class ActivityBuilder {
@PerActivity @PerActivity
@ContributesAndroidInjector( @ContributesAndroidInjector(
modules = [AuthenticationModule::class, modules = [AuthenticationModule::class,
OnBoardingFragmentProvider::class, OnBoardingFragmentProvider::class,
ServerFragmentProvider::class, ServerFragmentProvider::class,
LoginOptionsFragmentProvider::class, LoginOptionsFragmentProvider::class,
LoginFragmentProvider::class, LoginFragmentProvider::class,
RegisterUsernameFragmentProvider::class, RegisterUsernameFragmentProvider::class,
ResetPasswordFragmentProvider::class, ResetPasswordFragmentProvider::class,
SignupFragmentProvider::class, SignupFragmentProvider::class,
TwoFAFragmentProvider::class TwoFAFragmentProvider::class
] ]
) )
abstract fun bindAuthenticationActivity(): AuthenticationActivity abstract fun bindAuthenticationActivity(): AuthenticationActivity
...@@ -75,7 +79,16 @@ abstract class ActivityBuilder { ...@@ -75,7 +79,16 @@ abstract class ActivityBuilder {
@ContributesAndroidInjector( @ContributesAndroidInjector(
modules = [ modules = [
ChatRoomModule::class, ChatRoomModule::class,
ChatRoomFragmentProvider::class, ChatRoomFragmentProvider::class
]
)
abstract fun bindChatRoomActivity(): ChatRoomActivity
@PerActivity
@ContributesAndroidInjector(
modules = [
ChatDetailsModule::class,
ChatDetailsFragmentProvider::class,
MembersFragmentProvider::class, MembersFragmentProvider::class,
MentionsFragmentProvider::class, MentionsFragmentProvider::class,
PinnedMessagesFragmentProvider::class, PinnedMessagesFragmentProvider::class,
...@@ -83,7 +96,7 @@ abstract class ActivityBuilder { ...@@ -83,7 +96,7 @@ abstract class ActivityBuilder {
FilesFragmentProvider::class FilesFragmentProvider::class
] ]
) )
abstract fun bindChatRoomActivity(): ChatRoomActivity abstract fun bindChatDetailsActivity(): ChatDetailsActivity
@PerActivity @PerActivity
@ContributesAndroidInjector(modules = [PasswordFragmentProvider::class]) @ContributesAndroidInjector(modules = [PasswordFragmentProvider::class])
...@@ -96,6 +109,12 @@ abstract class ActivityBuilder { ...@@ -96,6 +109,12 @@ abstract class ActivityBuilder {
@PerActivity @PerActivity
@ContributesAndroidInjector(modules = [MessageInfoFragmentProvider::class]) @ContributesAndroidInjector(modules = [MessageInfoFragmentProvider::class])
abstract fun bindMessageInfoActiviy(): MessageInfoActivity abstract fun bindMessageInfoActiviy(): MessageInfoActivity
@PerActivity
@ContributesAndroidInjector(modules = [DrawModule::class]) @ContributesAndroidInjector(modules = [DrawModule::class])
abstract fun bindDrawingActivity(): DrawingActivity abstract fun bindDrawingActivity(): DrawingActivity
@PerActivity
@ContributesAndroidInjector(modules = [UserDetailsModule::class])
abstract fun bindUserDetailsActivity(): UserDetailsActivity
} }
...@@ -64,6 +64,7 @@ import chat.rocket.common.internal.ISO8601Date ...@@ -64,6 +64,7 @@ import chat.rocket.common.internal.ISO8601Date
import chat.rocket.common.model.TimestampAdapter import chat.rocket.common.model.TimestampAdapter
import chat.rocket.common.util.CalendarISO8601Converter import chat.rocket.common.util.CalendarISO8601Converter
import chat.rocket.common.util.Logger import chat.rocket.common.util.Logger
import chat.rocket.common.util.NoOpLogger
import chat.rocket.common.util.PlatformLogger import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.internal.AttachmentAdapterFactory import chat.rocket.core.internal.AttachmentAdapterFactory
import chat.rocket.core.internal.ReactionsAdapter import chat.rocket.core.internal.ReactionsAdapter
...@@ -231,7 +232,7 @@ class AppModule { ...@@ -231,7 +232,7 @@ class AppModule {
return Moshi.Builder() return Moshi.Builder()
.add(FallbackSealedClassJsonAdapter.ADAPTER_FACTORY) .add(FallbackSealedClassJsonAdapter.ADAPTER_FACTORY)
.add(AppJsonAdapterFactory.INSTANCE) .add(AppJsonAdapterFactory.INSTANCE)
.add(AttachmentAdapterFactory(Logger(logger, url))) .add(AttachmentAdapterFactory(NoOpLogger))
.add( .add(
java.lang.Long::class.java, java.lang.Long::class.java,
ISO8601Date::class.java, ISO8601Date::class.java,
......
...@@ -14,6 +14,7 @@ import chat.rocket.common.internal.ISO8601Date ...@@ -14,6 +14,7 @@ import chat.rocket.common.internal.ISO8601Date
import chat.rocket.common.model.TimestampAdapter import chat.rocket.common.model.TimestampAdapter
import chat.rocket.common.util.CalendarISO8601Converter import chat.rocket.common.util.CalendarISO8601Converter
import chat.rocket.common.util.Logger import chat.rocket.common.util.Logger
import chat.rocket.common.util.NoOpLogger
import chat.rocket.common.util.PlatformLogger import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.internal.AttachmentAdapterFactory import chat.rocket.core.internal.AttachmentAdapterFactory
import chat.rocket.core.internal.ReactionsAdapter import chat.rocket.core.internal.ReactionsAdapter
...@@ -47,7 +48,7 @@ class LocalModule { ...@@ -47,7 +48,7 @@ class LocalModule {
return Moshi.Builder() return Moshi.Builder()
.add(FallbackSealedClassJsonAdapter.ADAPTER_FACTORY) .add(FallbackSealedClassJsonAdapter.ADAPTER_FACTORY)
.add(AppJsonAdapterFactory.INSTANCE) .add(AppJsonAdapterFactory.INSTANCE)
.add(AttachmentAdapterFactory(Logger(logger, url))) .add(AttachmentAdapterFactory(NoOpLogger))
.add( .add(
java.lang.Long::class.java, java.lang.Long::class.java,
ISO8601Date::class.java, ISO8601Date::class.java,
...@@ -67,8 +68,6 @@ class LocalModule { ...@@ -67,8 +68,6 @@ class LocalModule {
return context.getSharedPreferences("rocket.chat", Context.MODE_PRIVATE) return context.getSharedPreferences("rocket.chat", Context.MODE_PRIVATE)
} }
@Provides @Provides
@Singleton @Singleton
fun provideLocalRepository(sharedPreferences: SharedPreferences, moshi: Moshi): LocalRepository { fun provideLocalRepository(sharedPreferences: SharedPreferences, moshi: Moshi): LocalRepository {
......
...@@ -9,7 +9,6 @@ import androidx.room.Transaction ...@@ -9,7 +9,6 @@ import androidx.room.Transaction
import androidx.room.Update import androidx.room.Update
import chat.rocket.android.db.model.ChatRoom import chat.rocket.android.db.model.ChatRoom
import chat.rocket.android.db.model.ChatRoomEntity import chat.rocket.android.db.model.ChatRoomEntity
import chat.rocket.common.model.RoomType
@Dao @Dao
abstract class ChatRoomDao : BaseDao<ChatRoomEntity> { abstract class ChatRoomDao : BaseDao<ChatRoomEntity> {
...@@ -18,7 +17,14 @@ abstract class ChatRoomDao : BaseDao<ChatRoomEntity> { ...@@ -18,7 +17,14 @@ abstract class ChatRoomDao : BaseDao<ChatRoomEntity> {
$BASE_QUERY $BASE_QUERY
WHERE chatrooms.id = :id WHERE chatrooms.id = :id
""") """)
abstract fun get(id: String): ChatRoom? abstract fun get(id: String): LiveData<ChatRoom>
@Transaction
@Query("""
$BASE_QUERY
WHERE chatrooms.id = :id
""")
abstract fun getSync(id: String): ChatRoom?
@Transaction @Transaction
@Query("$BASE_QUERY $FILTER_NOT_OPENED") @Query("$BASE_QUERY $FILTER_NOT_OPENED")
......
...@@ -98,7 +98,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -98,7 +98,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
suspend fun getRoom(id: String) = withContext(dbManagerContext) { suspend fun getRoom(id: String) = withContext(dbManagerContext) {
retryDB("getRoom($id)") { retryDB("getRoom($id)") {
chatRoomDao().get(id) chatRoomDao().getSync(id)
} }
} }
...@@ -338,7 +338,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -338,7 +338,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
} }
private suspend fun updateRoom(data: Room): ChatRoomEntity? { private suspend fun updateRoom(data: Room): ChatRoomEntity? {
return retryDB("getChatRoom(${data.id})") { chatRoomDao().get(data.id) }?.let { current -> return retryDB("getChatRoom(${data.id})") { chatRoomDao().getSync(data.id) }?.let { current ->
with(data) { with(data) {
val chatRoom = current.chatRoom val chatRoom = current.chatRoom
...@@ -351,10 +351,13 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -351,10 +351,13 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
ownerId = user?.id ?: chatRoom.ownerId, ownerId = user?.id ?: chatRoom.ownerId,
readonly = readonly, readonly = readonly,
updatedAt = updatedAt ?: chatRoom.updatedAt, updatedAt = updatedAt ?: chatRoom.updatedAt,
topic = topic,
announcement = announcement,
description = description,
lastMessageText = mapLastMessageText(lastMessage), lastMessageText = mapLastMessageText(lastMessage),
lastMessageUserId = lastMessage?.sender?.id, lastMessageUserId = lastMessage?.sender?.id,
lastMessageTimestamp = lastMessage?.timestamp, lastMessageTimestamp = lastMessage?.timestamp,
muted = muted muted = muted ?: chatRoom.muted
) )
} }
} }
...@@ -376,7 +379,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -376,7 +379,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
context.getString(R.string.msg_sent_attachment) context.getString(R.string.msg_sent_attachment)
private suspend fun updateSubscription(data: Subscription): ChatRoomEntity? { private suspend fun updateSubscription(data: Subscription): ChatRoomEntity? {
return retryDB("getRoom(${data.roomId}") { chatRoomDao().get(data.roomId) }?.let { current -> return retryDB("getRoom(${data.roomId}") { chatRoomDao().getSync(data.roomId) }?.let { current ->
with(data) { with(data) {
val userId = if (type is RoomType.DirectMessage) { val userId = if (type is RoomType.DirectMessage) {
...@@ -399,6 +402,9 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -399,6 +402,9 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
readonly = readonly ?: chatRoom.readonly, readonly = readonly ?: chatRoom.readonly,
isDefault = isDefault, isDefault = isDefault,
favorite = isFavorite, favorite = isFavorite,
topic = chatRoom.topic,
announcement = chatRoom.announcement,
description = chatRoom.description,
open = open, open = open,
alert = alert, alert = alert,
unread = unread, unread = unread,
...@@ -464,6 +470,9 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -464,6 +470,9 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
readonly = subscription.readonly, readonly = subscription.readonly,
isDefault = subscription.isDefault, isDefault = subscription.isDefault,
favorite = subscription.isFavorite, favorite = subscription.isFavorite,
topic = room.topic,
announcement = room.announcement,
description = room.description,
open = subscription.open, open = subscription.open,
alert = subscription.alert, alert = subscription.alert,
unread = subscription.unread, unread = subscription.unread,
...@@ -501,6 +510,9 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -501,6 +510,9 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
readonly = readonly, readonly = readonly,
isDefault = default, isDefault = default,
favorite = favorite, favorite = favorite,
topic = topic,
announcement = announcement,
description = description,
open = open, open = open,
alert = alert, alert = alert,
unread = unread, unread = unread,
......
...@@ -25,7 +25,7 @@ import chat.rocket.android.emoji.internal.db.StringListConverter ...@@ -25,7 +25,7 @@ import chat.rocket.android.emoji.internal.db.StringListConverter
AttachmentFieldEntity::class, AttachmentActionEntity::class, UrlEntity::class, AttachmentFieldEntity::class, AttachmentActionEntity::class, UrlEntity::class,
ReactionEntity::class, MessagesSync::class ReactionEntity::class, MessagesSync::class
], ],
version = 12, version = 11,
exportSchema = true exportSchema = true
) )
@TypeConverters(StringListConverter::class) @TypeConverters(StringListConverter::class)
......
...@@ -29,7 +29,7 @@ abstract class UserDao : BaseDao<UserEntity> { ...@@ -29,7 +29,7 @@ abstract class UserDao : BaseDao<UserEntity> {
abstract fun findUser(id: String): String? abstract fun findUser(id: String): String?
@Query("SELECT * FROM users WHERE ID = :id") @Query("SELECT * FROM users WHERE ID = :id")
abstract fun getUser(id:String): UserEntity? abstract fun getUser(id: String): UserEntity?
@Transaction @Transaction
open fun upsert(user: BaseUserEntity) { open fun upsert(user: BaseUserEntity) {
......
...@@ -34,6 +34,9 @@ data class ChatRoomEntity( ...@@ -34,6 +34,9 @@ data class ChatRoomEntity(
var readonly: Boolean? = false, var readonly: Boolean? = false,
var isDefault: Boolean? = false, var isDefault: Boolean? = false,
var favorite: Boolean? = false, var favorite: Boolean? = false,
var topic: String? = null,
var announcement: String? = null,
var description: String? = null,
var open: Boolean = true, var open: Boolean = true,
var alert: Boolean = false, var alert: Boolean = false,
var unread: Long = 0, var unread: Long = 0,
......
...@@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView ...@@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.chatroom.adapter.ChatRoomAdapter import chat.rocket.android.chatroom.adapter.ChatRoomAdapter
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatroom.uimodel.BaseUiModel import chat.rocket.android.chatroom.uimodel.BaseUiModel
...@@ -115,9 +116,9 @@ class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView { ...@@ -115,9 +116,9 @@ class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView {
} }
private fun setupToolbar() { private fun setupToolbar() {
(activity as ChatRoomActivity).let { (activity as ChatDetailsActivity).let {
it.showToolbarTitle(getString(R.string.title_favorite_messages)) it.setToolbarTitle(getString(R.string.title_favorite_messages))
it.hideToolbarChatRoomIcon() it.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
} }
} }
} }
\ No newline at end of file
...@@ -15,7 +15,7 @@ import androidx.recyclerview.widget.RecyclerView ...@@ -15,7 +15,7 @@ import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.files.adapter.FilesAdapter import chat.rocket.android.files.adapter.FilesAdapter
import chat.rocket.android.files.presentation.FilesPresenter import chat.rocket.android.files.presentation.FilesPresenter
import chat.rocket.android.files.presentation.FilesView import chat.rocket.android.files.presentation.FilesView
...@@ -152,9 +152,9 @@ class FilesFragment : Fragment(), FilesView { ...@@ -152,9 +152,9 @@ class FilesFragment : Fragment(), FilesView {
} }
private fun setupToolbar(totalFiles: Long) { private fun setupToolbar(totalFiles: Long) {
(activity as ChatRoomActivity).let { (activity as ChatDetailsActivity).let {
it.showToolbarTitle(getString(R.string.title_files_total, totalFiles)) it.setToolbarTitle(getString(R.string.title_files_total, totalFiles))
it.hideToolbarChatRoomIcon() it.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
} }
} }
} }
\ No newline at end of file
...@@ -110,6 +110,7 @@ class MainPresenter @Inject constructor( ...@@ -110,6 +110,7 @@ class MainPresenter @Inject constructor(
} }
fun loadCurrentInfo() { fun loadCurrentInfo() {
setupConnectionInfo(currentServer)
checkServerInfo(currentServer) checkServerInfo(currentServer)
launchUI(strategy) { launchUI(strategy) {
try { try {
......
...@@ -47,4 +47,4 @@ class MembersAdapter(private val listener: (MemberUiModel) -> Unit) : ...@@ -47,4 +47,4 @@ class MembersAdapter(private val listener: (MemberUiModel) -> Unit) :
setOnClickListener { listener(memberUiModel) } setOnClickListener { listener(memberUiModel) }
} }
} }
} }
\ No newline at end of file
package chat.rocket.android.members.di package chat.rocket.android.members.di
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.members.presentation.MembersNavigator import chat.rocket.android.members.presentation.MembersNavigator
...@@ -22,7 +22,7 @@ class MembersFragmentModule { ...@@ -22,7 +22,7 @@ class MembersFragmentModule {
@Provides @Provides
@PerFragment @PerFragment
fun provideChatRoomNavigator(activity: ChatRoomActivity) = MembersNavigator(activity) fun provideChatRoomNavigator(activity: ChatDetailsActivity) = MembersNavigator(activity)
@Provides @Provides
@PerFragment @PerFragment
......
package chat.rocket.android.members.presentation package chat.rocket.android.members.presentation
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.members.ui.TAG_MEMBER_BOTTOM_SHEET_FRAGMENT import chat.rocket.android.userdetails.ui.userDetailsIntent
import chat.rocket.android.members.ui.newInstance
class MembersNavigator(internal val activity: ChatRoomActivity) { class MembersNavigator(internal val activity: ChatDetailsActivity) {
fun toMemberDetails(avatarUri: String, realName: String, username: String, email: String, utcOffset: String) { fun toMemberDetails(userId: String) {
activity.apply { activity.apply {
newInstance(avatarUri, realName, username, email, utcOffset) startActivity(this.userDetailsIntent(userId, ""))
.show(supportFragmentManager, TAG_MEMBER_BOTTOM_SHEET_FRAGMENT)
} }
} }
} }
...@@ -59,12 +59,6 @@ class MembersPresenter @Inject constructor( ...@@ -59,12 +59,6 @@ class MembersPresenter @Inject constructor(
} }
fun toMemberDetails(memberUiModel: MemberUiModel) { fun toMemberDetails(memberUiModel: MemberUiModel) {
navigator.toMemberDetails( navigator.toMemberDetails(memberUiModel.userId)
memberUiModel.avatarUri.toString(),
memberUiModel.realName.toString(),
"@${memberUiModel.username}",
memberUiModel.email ?: "",
memberUiModel.utcOffset.toString()
)
} }
} }
\ No newline at end of file
...@@ -12,7 +12,7 @@ import androidx.recyclerview.widget.RecyclerView ...@@ -12,7 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.members.adapter.MembersAdapter import chat.rocket.android.members.adapter.MembersAdapter
import chat.rocket.android.members.presentation.MembersPresenter import chat.rocket.android.members.presentation.MembersPresenter
...@@ -127,13 +127,13 @@ class MembersFragment : Fragment(), MembersView { ...@@ -127,13 +127,13 @@ class MembersFragment : Fragment(), MembersView {
} }
private fun setupToolbar(totalMembers: Long? = null) { private fun setupToolbar(totalMembers: Long? = null) {
(activity as ChatRoomActivity).let { (activity as ChatDetailsActivity).let {
if (totalMembers != null) { if (totalMembers != null) {
it.showToolbarTitle(getString(R.string.title_counted_members, totalMembers)) it.setToolbarTitle(getString(R.string.title_counted_members, totalMembers))
} else { } else {
it.showToolbarTitle(getString(R.string.title_members)) it.setToolbarTitle(getString(R.string.title_members))
} }
it.hideToolbarChatRoomIcon() it.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
} }
} }
} }
\ No newline at end of file
...@@ -11,6 +11,7 @@ class MemberUiModel( ...@@ -11,6 +11,7 @@ class MemberUiModel(
private val settings: Map<String, Value<Any>>, private val settings: Map<String, Value<Any>>,
private val baseUrl: String? private val baseUrl: String?
) { ) {
val userId: String = member.id
val avatarUri: String? val avatarUri: String?
val displayName: String val displayName: String
val realName: String? val realName: String?
...@@ -52,4 +53,4 @@ class MemberUiModel( ...@@ -52,4 +53,4 @@ class MemberUiModel(
private fun getUserUtcOffset(): Float? = member.utcOffset private fun getUserUtcOffset(): Float? = member.utcOffset
private fun getUserStatus(): UserStatus? = member.status private fun getUserStatus(): UserStatus? = member.status
} }
\ No newline at end of file
...@@ -7,11 +7,14 @@ import chat.rocket.common.model.User ...@@ -7,11 +7,14 @@ import chat.rocket.common.model.User
import chat.rocket.core.model.Value import chat.rocket.core.model.Value
import javax.inject.Inject import javax.inject.Inject
class MemberUiModelMapper @Inject constructor(serverInteractor: GetCurrentServerInteractor, getSettingsInteractor: GetSettingsInteractor) { class MemberUiModelMapper @Inject constructor(
serverInteractor: GetCurrentServerInteractor,
getSettingsInteractor: GetSettingsInteractor
) {
private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!) private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!)
private val baseUrl = settings.baseUrl() private val baseUrl = settings.baseUrl()
fun mapToUiModelList(memberList: List<User>): List<MemberUiModel> { fun mapToUiModelList(memberList: List<User>): List<MemberUiModel> {
return memberList.map { MemberUiModel(it, settings, baseUrl) } return memberList.map { MemberUiModel(it, settings, baseUrl) }
} }
} }
\ No newline at end of file
...@@ -12,8 +12,8 @@ import androidx.recyclerview.widget.RecyclerView ...@@ -12,8 +12,8 @@ import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.chatroom.adapter.ChatRoomAdapter import chat.rocket.android.chatroom.adapter.ChatRoomAdapter
import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatroom.uimodel.BaseUiModel import chat.rocket.android.chatroom.uimodel.BaseUiModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.mentions.presentention.MentionsPresenter import chat.rocket.android.mentions.presentention.MentionsPresenter
...@@ -122,9 +122,9 @@ class MentionsFragment : Fragment(), MentionsView { ...@@ -122,9 +122,9 @@ class MentionsFragment : Fragment(), MentionsView {
} }
private fun setupToolbar() { private fun setupToolbar() {
(activity as ChatRoomActivity).let { (activity as ChatDetailsActivity).let {
it.showToolbarTitle(getString(R.string.msg_mentions)) it.setToolbarTitle(getString(R.string.msg_mentions))
it.hideToolbarChatRoomIcon() it.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
} }
} }
} }
\ No newline at end of file
...@@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView ...@@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.chatdetails.ui.ChatDetailsActivity
import chat.rocket.android.chatroom.adapter.ChatRoomAdapter import chat.rocket.android.chatroom.adapter.ChatRoomAdapter
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatroom.uimodel.BaseUiModel import chat.rocket.android.chatroom.uimodel.BaseUiModel
...@@ -122,9 +123,9 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView { ...@@ -122,9 +123,9 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
} }
private fun setupToolbar() { private fun setupToolbar() {
(activity as ChatRoomActivity).let { (activity as ChatDetailsActivity).let {
it.showToolbarTitle(getString(R.string.title_pinned_messages)) it.setToolbarTitle(getString(R.string.title_pinned_messages))
it.hideToolbarChatRoomIcon() it.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
} }
} }
} }
\ No newline at end of file
...@@ -30,6 +30,7 @@ class RocketChatClientFactory @Inject constructor( ...@@ -30,6 +30,7 @@ class RocketChatClientFactory @Inject constructor(
userAgent = "RC Mobile; Android ${Build.VERSION.RELEASE}; v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" userAgent = "RC Mobile; Android ${Build.VERSION.RELEASE}; v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
tokenRepository = repository tokenRepository = repository
platformLogger = logger platformLogger = logger
enableLogger = false
} }
Timber.d("Returning NEW client for: $url") Timber.d("Returning NEW client for: $url")
......
...@@ -35,10 +35,6 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback { ...@@ -35,10 +35,6 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
private var actionMode: ActionMode? = null private var actionMode: ActionMode? = null
private val disposables = CompositeDisposable() private val disposables = CompositeDisposable()
companion object {
fun newInstance() = PasswordFragment()
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -143,4 +139,8 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback { ...@@ -143,4 +139,8 @@ class PasswordFragment : Fragment(), PasswordView, ActionMode.Callback {
actionMode = (activity as PasswordActivity).startSupportActionMode(this) actionMode = (activity as PasswordActivity).startSupportActionMode(this)
} }
} }
}
\ No newline at end of file companion object {
fun newInstance() = PasswordFragment()
}
}
package chat.rocket.android.userdetails.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.userdetails.presentation.UserDetailsView
import chat.rocket.android.userdetails.ui.UserDetailsActivity
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
@Module
class UserDetailsModule {
@Provides
@PerActivity
fun provideJob() = Job()
@Provides
@PerActivity
fun provideUserDetailsView(activity: UserDetailsActivity): UserDetailsView = activity
@Provides
@PerActivity
fun provideLifecycleOwner(activity: UserDetailsActivity): LifecycleOwner = activity
@Provides
@PerActivity
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
}
package chat.rocket.android.userdetails.presentation
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.domain.GetConnectingServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.retryIO
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.model.userStatusOf
import chat.rocket.core.internal.rest.createDirectMessage
import chat.rocket.core.model.ChatRoom
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.withContext
import timber.log.Timber
import javax.inject.Inject
class UserDetailsPresenter @Inject constructor(
private val view: UserDetailsView,
private val dbManager: DatabaseManager,
private val strategy: CancelStrategy,
serverInteractor: GetConnectingServerInteractor,
factory: ConnectionManagerFactory
) {
private var currentServer = serverInteractor.get()!!
private val manager = factory.create(currentServer)
private val client = manager.client
fun loadUserDetails(userId: String) {
launchUI(strategy) {
try {
val user = withContext(CommonPool) {
dbManager.userDao().getUser(id = userId)
}
user?.let { u ->
val openedChatRooms = chatRoomByName(name = u.name)
val avatarUrl = u.username?.let { currentServer.avatarUrl(avatar = it) }
val chatRoom: ChatRoom? = if (openedChatRooms.isEmpty()) {
ChatRoom(
id = "",
type = roomTypeOf(RoomType.DIRECT_MESSAGE),
name = u.username ?: u.name.orEmpty(),
fullName = u.name,
favorite = false,
open = false,
alert = false,
status = userStatusOf(u.status),
client = client,
broadcast = false,
archived = false,
default = false,
description = null,
groupMentions = null,
userMentions = null,
lastMessage = null,
lastSeen = null,
topic = null,
announcement = null,
roles = null,
unread = 0,
readonly = false,
muted = null,
subscriptionId = "",
timestamp = null,
updatedAt = null,
user = null
)
} else openedChatRooms.firstOrNull()
view.showUserDetails(
avatarUrl = avatarUrl,
username = u.username,
name = u.name,
utcOffset = u.utcOffset,
status = u.status,
chatRoom = chatRoom
)
}
} catch (ex: Exception) {
Timber.e(ex)
}
}
}
fun createDirectMessage(id: String) = launchUI(strategy) {
try {
val result = retryIO("createDirectMessage($id") {
client.createDirectMessage(username = id)
}
val userEntity = withContext(CommonPool) {
dbManager.userDao().getUser(id = id)
}
if (userEntity != null) {
view.toDirectMessage(
chatRoom = ChatRoom(
id = result.id,
type = roomTypeOf(RoomType.DIRECT_MESSAGE),
name = userEntity.username ?: userEntity.name.orEmpty(),
fullName = userEntity.name,
favorite = false,
open = false,
alert = false,
status = userStatusOf(userEntity.status),
client = client,
broadcast = false,
archived = false,
default = false,
description = null,
groupMentions = null,
userMentions = null,
lastMessage = null,
lastSeen = null,
topic = null,
announcement = null,
roles = null,
unread = 0,
readonly = false,
muted = null,
subscriptionId = "",
timestamp = null,
updatedAt = result.updatedAt,
user = null
)
)
}
} catch (ex: Exception) {
Timber.e(ex)
view.onOpenDirectMessageError()
}
}
private suspend fun chatRoomByName(name: String? = null): List<ChatRoom> = withContext(CommonPool) {
return@withContext dbManager.chatRoomDao().getAllSync().filter {
if (name == null) {
return@filter true
}
it.chatRoom.name == name || it.chatRoom.fullname == name
}.map {
with(it.chatRoom) {
ChatRoom(
id = id,
subscriptionId = subscriptionId,
type = roomTypeOf(type),
unread = unread,
broadcast = broadcast ?: false,
alert = alert,
fullName = fullname,
name = name ?: "",
favorite = favorite ?: false,
default = isDefault ?: false,
readonly = readonly,
open = open,
lastMessage = null,
archived = false,
status = null,
user = null,
userMentions = userMentions,
client = client,
announcement = null,
description = null,
groupMentions = groupMentions,
roles = null,
topic = null,
lastSeen = this.lastSeen,
timestamp = timestamp,
updatedAt = updatedAt
)
}
}
}
}
package chat.rocket.android.userdetails.presentation
import chat.rocket.core.model.ChatRoom
interface UserDetailsView {
fun showUserDetails(avatarUrl: String?, username: String?, name: String?, utcOffset: Float?, status: String, chatRoom: ChatRoom?)
fun toDirectMessage(chatRoom: ChatRoom)
fun onOpenDirectMessageError()
}
package chat.rocket.android.userdetails.ui
import android.content.Context
import android.content.Intent
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import blurred
import chat.rocket.android.R
import chat.rocket.android.chatroom.ui.chatRoomIntent
import chat.rocket.android.emoji.internal.GlideApp
import chat.rocket.android.userdetails.presentation.UserDetailsPresenter
import chat.rocket.android.userdetails.presentation.UserDetailsView
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extension.orFalse
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.retryIO
import chat.rocket.common.model.roomTypeOf
import chat.rocket.core.internal.rest.createDirectMessage
import chat.rocket.core.model.ChatRoom
import chat.rocket.core.model.userId
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.CenterInside
import com.bumptech.glide.load.resource.bitmap.FitCenter
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.google.android.material.snackbar.Snackbar
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.activity_user_details.*
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext
import org.threeten.bp.OffsetDateTime
import org.threeten.bp.ZoneId
import org.threeten.bp.ZoneOffset
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.format.DateTimeFormatter
import timber.log.Timber
import javax.inject.Inject
import kotlin.math.roundToLong
fun Context.userDetailsIntent(userId: String, subscriptionId: String): Intent {
return Intent(this, UserDetailsActivity::class.java).apply {
putExtra(EXTRA_USER_ID, userId)
putExtra(EXTRA_SUBSCRIPTION_ID, subscriptionId)
}
}
const val EXTRA_USER_ID = "EXTRA_USER_ID"
const val EXTRA_SUBSCRIPTION_ID = "EXTRA_USERNAME"
class UserDetailsActivity : AppCompatActivity(), UserDetailsView, HasSupportFragmentInjector {
@Inject
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
@Inject
lateinit var presenter: UserDetailsPresenter
private lateinit var subscriptionId: String
private lateinit var userId: String
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user_details)
setupToolbar()
userId = intent.getStringExtra(EXTRA_USER_ID)
subscriptionId = intent.getStringExtra(EXTRA_SUBSCRIPTION_ID)
showLoadingView(true)
presenter.loadUserDetails(userId = userId)
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> = fragmentDispatchingAndroidInjector
private fun setupToolbar() {
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false)
toolbar.setNavigationOnClickListener { finish() }
}
override fun showUserDetails(
avatarUrl: String?,
username: String?,
name: String?,
utcOffset: Float?,
status: String,
chatRoom: ChatRoom?
) {
text_view_name.text = name
text_view_username.text = username
text_view_status.text = status.capitalize()
try {
launch(UI) {
val image = withContext(CommonPool) {
try {
val requestOptions = RequestOptions()
.priority(Priority.IMMEDIATE)
.transforms(CenterInside(), FitCenter())
return@withContext GlideApp.with(this@UserDetailsActivity)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.load(avatarUrl)
.apply(requestOptions)
.submit()
.get()
} catch (ex: Exception) {
Timber.e(ex)
return@withContext null
} finally {
showLoadingView(false)
}
}
image?.let {
val blurredBitmap = image.blurred(context = this@UserDetailsActivity,
newWidth = toolbar.measuredWidth, newHeight = toolbar.measuredHeight)
toolbar.background = BitmapDrawable(resources, blurredBitmap)
GlideApp.with(this@UserDetailsActivity)
.asBitmap()
.transforms(RoundedCorners(25), CenterCrop())
.load(image)
.into(image_view_avatar)
}
}
utcOffset?.let {
val offsetLong = it.roundToLong()
val offset = if (it > 0) "+$offsetLong" else offsetLong.toString()
val formatter = DateTimeFormatter.ofPattern("'(GMT$offset)' hh:mm a")
val zoneId = ZoneId.systemDefault()
val timeNow = OffsetDateTime.now(ZoneOffset.UTC).plusHours(offsetLong).toLocalDateTime()
text_view_tz.text = formatter.format(ZonedDateTime.of(timeNow, zoneId))
}
text_view_message.setOnClickListener {
if (chatRoom == null) {
presenter.createDirectMessage(id = userId)
} else {
toDirectMessage(chatRoom)
}
}
image_view_message.setOnClickListener {
if (chatRoom == null) {
presenter.createDirectMessage(id = userId)
} else {
toDirectMessage(chatRoom)
}
}
} catch (ex: Exception) {
Timber.e(ex)
}
}
private fun showLoadingView(show: Boolean) {
runOnUiThread {
group_user_details.isVisible = !show
view_loading.isVisible = show
}
}
override fun onOpenDirectMessageError() {
Snackbar.make(root_layout, R.string.error_opening_dm, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.retry) {
presenter.createDirectMessage(userId)
}.show()
}
override fun toDirectMessage(chatRoom: ChatRoom) {
finish()
if (chatRoom.subscriptionId.isEmpty() || chatRoom.subscriptionId != subscriptionId) {
startActivity(
chatRoomIntent(
chatRoomId = chatRoom.id,
chatRoomName = chatRoom.name,
chatRoomType = chatRoom.type.toString(),
isReadOnly = chatRoom.readonly.orFalse(),
chatRoomLastSeen = chatRoom.lastSeen ?: 0,
isSubscribed = chatRoom.open,
isCreator = false,
isFavorite = chatRoom.favorite
)
)
}
}
}
import android.content.Context
import android.graphics.Bitmap
import android.renderscript.Allocation
import android.renderscript.Element
import android.renderscript.RenderScript
import android.renderscript.ScriptIntrinsicBlur
fun Bitmap.blurred(context: Context, intensity: Float = 25f, newWidth: Int = -1, newHeight: Int = -1): Bitmap {
if (intensity <= 0 || intensity > 25) {
throw IllegalStateException("Intensity out of range (0 < intensity <= 25).")
}
val nonScaledBitmap = copy(config, true)
val bitmap = if (newWidth > 0 && newHeight > 0) {
val height = nonScaledBitmap.height
val width = nonScaledBitmap.width
val aspectRadio = width / height
val adjustedWidth = newHeight * aspectRadio
val adjustedHeight = newWidth * height / width
val scaledBitmap = Bitmap.createScaledBitmap(nonScaledBitmap, adjustedWidth, adjustedHeight, false)
Bitmap.createBitmap(scaledBitmap, 0, 0, adjustedWidth, newHeight)
} else nonScaledBitmap
val rs = RenderScript.create(context)
val input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT)
val output = Allocation.createTyped(rs, input.type)
val script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
script.setRadius(intensity)
script.setInput(input)
script.forEach(output)
output.copyTo(bitmap)
return bitmap
}
...@@ -76,4 +76,10 @@ fun String.lowercaseUrl(): String? { ...@@ -76,4 +76,10 @@ fun String.lowercaseUrl(): String? {
return httpUrl?.newBuilder()?.scheme(newScheme)?.build()?.toString() return httpUrl?.newBuilder()?.scheme(newScheme)?.build()?.toString()
} }
fun String?.isNotNullNorEmpty(): Boolean = this != null && this.isNotEmpty() fun String?.isNotNullNorEmpty(): Boolean = this != null && this.isNotEmpty()
\ No newline at end of file
inline fun String?.ifNotNullNotEmpty(block: (String) -> Unit) {
if (this != null && this.isNotEmpty()) {
block(this)
}
}
\ No newline at end of file
...@@ -118,4 +118,4 @@ fun Menu.toList(): List<MenuItem> { ...@@ -118,4 +118,4 @@ fun Menu.toList(): List<MenuItem> {
val menuItems = ArrayList<MenuItem>(this.size()) val menuItems = ArrayList<MenuItem>(this.size())
(0 until this.size()).mapTo(menuItems) { this.getItem(it) } (0 until this.size()).mapTo(menuItems) { this.getItem(it) }
return menuItems return menuItems
} }
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<solid android:color="@android:color/white" />
<corners android:radius="25px" />
</shape>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="@color/actionMenuColor"
android:pathData="M10.11,16.546h-0.183c-4.329,0 -7.47,-2.753 -7.47,-6.546 0,-3.61 2.942,-6.547 6.56,-6.547 3.616,0 6.56,2.937 6.56,6.547 0,0.59 -0.276,1.18 -0.567,1.803 -0.1,0.218 -0.2,0.433 -0.278,0.618 -0.756,1.626 0.731,2.41 1.364,2.743 0.098,0.051 0.224,0.117 0.326,0.178 -0.416,0.478 -1.814,1.22 -6.312,1.204m6.666,-2.667c-0.895,-0.473 -0.852,-0.567 -0.71,-0.875 0.081,-0.193 0.172,-0.389 0.264,-0.587 0.33,-0.705 0.703,-1.505 0.703,-2.417 0,-4.412 -3.597,-8 -8.017,-8S1,5.588 1,10c0,4.635 3.755,8 8.927,8h0.382c2.857,0 6.632,-0.256 7.565,-2.237 0.493,-1.046 -0.58,-1.612 -1.098,-1.884" />
</vector>
...@@ -3,10 +3,8 @@ ...@@ -3,10 +3,8 @@
android:height="24dp" android:height="24dp"
android:viewportHeight="17.0" android:viewportHeight="17.0"
android:viewportWidth="18.0"> android:viewportWidth="18.0">
<path <path
android:fillColor="#FF1D74F5" android:fillColor="#FF1D74F5"
android:fillType="nonZero" android:fillType="nonZero"
android:pathData="M4.221,11.799L10.444,5.576C10.97,5.05 11.833,5.067 12.383,5.617C12.928,6.163 12.946,7.034 12.423,7.557L6.195,13.785C5.226,14.754 3.613,14.717 2.599,13.704C1.582,12.687 1.546,11.08 2.52,10.106L9.295,3.331C10.713,1.913 13.07,1.966 14.552,3.448C16.035,4.931 16.087,7.287 14.668,8.706L7.898,15.476L8.747,16.324L15.516,9.555C17.383,7.688 17.316,4.588 15.364,2.636C13.414,0.686 10.313,0.616 8.446,2.483L1.671,9.258C0.248,10.681 0.302,13.03 1.788,14.515C3.27,15.997 5.626,16.051 7.044,14.633L13.272,8.405C14.242,7.435 14.209,5.82 13.195,4.805C12.175,3.786 10.569,3.754 9.595,4.728L3.373,10.95L4.221,11.799Z" /> android:pathData="M4.221,11.799L10.444,5.576C10.97,5.05 11.833,5.067 12.383,5.617C12.928,6.163 12.946,7.034 12.423,7.557L6.195,13.785C5.226,14.754 3.613,14.717 2.599,13.704C1.582,12.687 1.546,11.08 2.52,10.106L9.295,3.331C10.713,1.913 13.07,1.966 14.552,3.448C16.035,4.931 16.087,7.287 14.668,8.706L7.898,15.476L8.747,16.324L15.516,9.555C17.383,7.688 17.316,4.588 15.364,2.636C13.414,0.686 10.313,0.616 8.446,2.483L1.671,9.258C0.248,10.681 0.302,13.03 1.788,14.515C3.27,15.997 5.626,16.051 7.044,14.633L13.272,8.405C14.242,7.435 14.209,5.82 13.195,4.805C12.175,3.786 10.569,3.754 9.595,4.728L3.373,10.95L4.221,11.799Z" />
</vector> </vector>
\ No newline at end of file
<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="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
</vector>
<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>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M16.5,13c-1.2,0 -3.07,0.34 -4.5,1 -1.43,-0.67 -3.3,-1 -4.5,-1C5.33,13 1,14.08 1,16.25L1,19h22v-2.75c0,-2.17 -4.33,-3.25 -6.5,-3.25zM12.5,17.5h-10v-1.25c0,-0.54 2.56,-1.75 5,-1.75s5,1.21 5,1.75v1.25zM21.5,17.5L14,17.5v-1.25c0,-0.46 -0.2,-0.86 -0.52,-1.22 0.88,-0.3 1.96,-0.53 3.02,-0.53 2.44,0 5,1.21 5,1.75v1.25zM7.5,12c1.93,0 3.5,-1.57 3.5,-3.5S9.43,5 7.5,5 4,6.57 4,8.5 5.57,12 7.5,12zM7.5,6.5c1.1,0 2,0.9 2,2s-0.9,2 -2,2 -2,-0.9 -2,-2 0.9,-2 2,-2zM16.5,12c1.93,0 3.5,-1.57 3.5,-3.5S18.43,5 16.5,5 13,6.57 13,8.5s1.57,3.5 3.5,3.5zM16.5,6.5c1.1,0 2,0.9 2,2s-0.9,2 -2,2 -2,-0.9 -2,-2 0.9,-2 2,-2z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"> android:shape="rectangle">
<solid android:color="@color/colorAccent" /> <solid android:color="@color/colorAccent" />
<corners android:radius="4dp" />
</shape> </shape>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".chatdetails.ui.ChatDetailsActivity">
<include
android:id="@+id/layout_app_bar"
layout="@layout/app_bar_chat_details" />
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
\ No newline at end of file
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
android:orientation="vertical" android:orientation="vertical"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:context=".settings.password.ui.PasswordActivity"> tools:context=".settings.password.ui.PasswordActivity">
<include <include
android:id="@+id/layout_app_bar" android:id="@+id/layout_app_bar"
layout="@layout/app_bar_password" /> layout="@layout/app_bar_password" />
<FrameLayout <FrameLayout
android:id="@+id/fragment_container" android:id="@+id/fragment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
</LinearLayout> </LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:fitsSystemWindows="true">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/view_loading"
style="@style/Authentication.AVLoadingIndicatorView"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<ImageView
android:id="@+id/image_view_message"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_username"
app:srcCompat="@drawable/ic_message_24dp" />
<TextView
android:id="@+id/text_view_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message"
android:textColor="#1d74f5"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="@+id/image_view_message"
app:layout_constraintStart_toStartOf="@+id/image_view_message"
app:layout_constraintTop_toBottomOf="@+id/image_view_message" />
<TextView
android:id="@+id/text_view_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:fontFamily="sans-serif-medium"
android:textColor="@android:color/black"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Karem Flusser" />
<TextView
android:id="@+id/text_view_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textColor="@color/darkGray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_name"
tools:text="karem.flusser" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:text="@string/status"
android:textColor="@color/darkGray"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_message" />
<TextView
android:id="@+id/text_view_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textColor="@android:color/black"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3"
tools:text="Online" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/timezone"
android:textColor="@color/darkGray"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_status" />
<TextView
android:id="@+id/text_view_tz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textColor="@android:color/black"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:text="(UTC-2) 11:08 AM" />
<androidx.constraintlayout.widget.Group
android:id="@+id/group_user_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="text_view_tz,textView,text_view_status,text_view_message,textView3,text_view_name,text_view_username,image_view_message" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
app:elevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="@android:color/white"
app:expandedTitleGravity="top"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="?actionBarSize"
app:elevation="0dp"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:navigationIcon="?android:attr/homeAsUpIndicator"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<ImageView
android:id="@+id/image_view_avatar"
android:layout_width="98dp"
android:layout_height="98dp"
android:layout_gravity="center_horizontal"
android:layout_marginStart="16dp"
android:layout_marginTop="?actionBarSize"
android:layout_marginEnd="16dp"
android:background="@drawable/bg_round_bounds_white"
tools:srcCompat="@tools:sample/avatars[6]" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.appbar.AppBarLayout 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: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="@drawable/ic_close_white_24dp"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="@dimen/text_view_drawable_padding"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"
tools:text="@string/title_channel_details" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
\ No newline at end of file
<?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>-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/whitesmoke"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:background="@color/colorWhite"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="15dp">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/ChatDetails.Title.TextView"
android:drawablePadding="@dimen/text_view_drawable_padding"
tools:text="#important"/>
<TextView
android:id="@+id/title_topic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_marginTop="20dp"
style="@style/ChatDetails.Title.TextView"
android:text="@string/title_topic" />
<TextView
android:id="@+id/content_topic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title_topic"
style="@style/ChatDetails.Content.TextView"
android:text="@string/msg_no_topic" />
<TextView
android:id="@+id/title_announcement"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/content_topic"
android:layout_marginTop="15dp"
style="@style/ChatDetails.Title.TextView"
android:text="@string/title_announcement" />
<TextView
android:id="@+id/content_announcement"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title_announcement"
style="@style/ChatDetails.Content.TextView"
android:text="@string/msg_no_announcement" />
<TextView
android:id="@+id/title_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/content_announcement"
android:layout_marginTop="15dp"
style="@style/ChatDetails.Title.TextView"
android:text="@string/title_description" />
<TextView
android:id="@+id/content_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title_description"
android:layout_marginBottom="10dp"
style="@style/ChatDetails.Content.TextView"
android:text="@string/msg_no_description" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/options"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
\ No newline at end of file
...@@ -5,19 +5,19 @@ ...@@ -5,19 +5,19 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:paddingBottom="@dimen/chat_item_top_and_bottom_padding"
android:paddingEnd="@dimen/screen_edge_left_and_right_padding"
android:paddingStart="@dimen/screen_edge_left_and_right_padding" android:paddingStart="@dimen/screen_edge_left_and_right_padding"
android:paddingTop="@dimen/chat_item_top_and_bottom_padding"> android:paddingTop="@dimen/chat_item_top_and_bottom_padding"
android:paddingEnd="@dimen/screen_edge_left_and_right_padding"
android:paddingBottom="@dimen/chat_item_top_and_bottom_padding">
<com.facebook.drawee.view.SimpleDraweeView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image_avatar" android:id="@+id/image_avatar"
android:layout_width="40dp" android:layout_width="48dp"
android:layout_height="40dp" android:layout_height="48dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:roundedCornerRadius="3dp" /> app:roundedCornerRadius="4dp" />
<ImageView <ImageView
android:id="@+id/image_chat_icon" android:id="@+id/image_chat_icon"
...@@ -27,65 +27,50 @@ ...@@ -27,65 +27,50 @@
app:layout_constraintBottom_toBottomOf="@+id/text_chat_name" app:layout_constraintBottom_toBottomOf="@+id/text_chat_name"
app:layout_constraintStart_toEndOf="@+id/image_avatar" app:layout_constraintStart_toEndOf="@+id/image_avatar"
app:layout_constraintTop_toTopOf="@+id/text_chat_name" app:layout_constraintTop_toTopOf="@+id/text_chat_name"
tools:src="@drawable/ic_hashtag_unread_12dp" /> tools:src="@drawable/ic_hashtag_12dp" />
<TextView
android:id="@+id/text_last_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginTop="2dp"
android:layout_weight="0.8"
android:ellipsize="end"
android:maxLines="2"
android:textDirection="locale"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/image_chat_icon"
app:layout_constraintTop_toBottomOf="@+id/text_chat_name"
tools:text="Filipe de Lima Brito: Type something that is very big and need at least to lines, or maybe even more" />
<TextView <TextView
android:id="@+id/text_chat_name" android:id="@+id/text_chat_name"
style="@style/ChatRoom.Name.TextView" style="@style/ChatList.ChatName.TextView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/text_view_drawable_padding" android:layout_marginStart="@dimen/text_view_drawable_padding"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textDirection="locale" android:textDirection="locale"
android:textColor="@color/colorSecondaryText" app:layout_constraintEnd_toStartOf="@+id/text_timestamp"
app:layout_constraintBottom_toTopOf="@+id/text_last_message"
app:layout_constraintEnd_toStartOf="@+id/text_last_message_date_time"
app:layout_constraintStart_toEndOf="@+id/image_chat_icon" app:layout_constraintStart_toEndOf="@+id/image_chat_icon"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="general" /> tools:text="Margaret Hanson" />
<TextView <TextView
android:id="@+id/text_last_message_date_time" android:id="@+id/text_timestamp"
style="@style/Timestamp.TextView" style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
android:gravity="center" android:textDirection="locale"
android:layout_marginEnd="8dp" app:layout_constraintBaseline_toBaselineOf="@+id/text_chat_name"
app:layout_constraintBottom_toBottomOf="@+id/layout_unread_messages_badge" app:layout_constraintEnd_toEndOf="parent"
tools:text="11:45 AM" />
<TextView
android:id="@+id/text_last_message"
style="@style/ChatList.LastMessage.TextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:ellipsize="end" android:layout_marginEnd="12dp"
android:maxLines="2"
android:textDirection="locale" android:textDirection="locale"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge" app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge"
app:layout_constraintTop_toTopOf="@+id/text_chat_name" app:layout_constraintStart_toStartOf="@+id/image_chat_icon"
tools:text="11:45 AM" /> app:layout_constraintTop_toBottomOf="@+id/text_chat_name"
tools:text="Filipe de Lima Brito: Type something that is very big and need at least to lines, or maybe even more" />
<include <include
android:id="@+id/layout_unread_messages_badge" android:id="@+id/layout_unread_messages_badge"
layout="@layout/unread_messages_badge" layout="@layout/unread_messages_badge"
android:layout_width="18dp" android:layout_width="21dp"
android:layout_height="18dp" android:layout_height="21dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/text_chat_name" /> app:layout_constraintTop_toTopOf="@+id/text_last_message" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:padding="20dp">
<ImageView
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
tools:ignore="ContentDescription"
android:src="@drawable/ic_add_24dp"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/icon"
android:layout_alignBottom="@id/icon"
android:gravity="center_vertical"
android:layout_marginStart="57dp"
style="@style/ChatDetails.Title.TextView"
tools:text="Files"/>
</RelativeLayout>
\ No newline at end of file
...@@ -92,11 +92,11 @@ ...@@ -92,11 +92,11 @@
android:id="@+id/message_header" android:id="@+id/message_header"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@+id/layout_avatar" app:layout_constraintLeft_toRightOf="@+id/layout_avatar"
app:layout_constraintStart_toEndOf="@+id/layout_avatar" app:layout_constraintStart_toEndOf="@+id/layout_avatar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/day_marker_layout"> app:layout_constraintTop_toBottomOf="@+id/day_marker_layout">
<TextView <TextView
...@@ -104,13 +104,13 @@ ...@@ -104,13 +104,13 @@
style="@style/Sender.Name.TextView" style="@style/Sender.Name.TextView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_weight="1"
tools:text="User Name with long name" /> tools:text="User Name with long name" />
<TextView <TextView
android:id="@+id/text_message_time" android:id="@+id/text_message_time"
style="@style/Timestamp.TextView" style="@style/ChatRoom.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="4dp" android:layout_marginStart="4dp"
......
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
<TextView <TextView
android:id="@+id/text_message_time" android:id="@+id/text_message_time"
style="@style/Timestamp.TextView" style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
<TextView <TextView
android:id="@+id/text_message_time" android:id="@+id/text_message_time"
style="@style/Timestamp.TextView" style="@style/ChatList.Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
......
...@@ -6,15 +6,12 @@ ...@@ -6,15 +6,12 @@
<TextView <TextView
android:id="@+id/text_total_unread_messages" android:id="@+id/text_total_unread_messages"
style="@style/TextAppearance.AppCompat.Caption" style="@style/ChatList.Badge.TextView"
android:layout_width="18dp" android:layout_width="21dp"
android:layout_height="18dp" android:layout_height="21dp"
android:background="@drawable/style_total_unread_messages" android:background="@drawable/style_total_unread_messages"
android:gravity="center"
android:textColor="@color/colorWhite"
android:textSize="10sp"
android:visibility="gone" android:visibility="gone"
tools:text="99+" tools:text="1"
tools:visibility="visible" /> tools:visibility="visible" />
</LinearLayout> </LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:app="http://schemas.android.com/apk/res-auto">
<item <item
android:id="@+id/action_message_info" android:id="@+id/action_message_info"
android:icon="@drawable/ic_action_message_info_outline_24dp" android:icon="@drawable/ic_action_message_info_outline_24dp"
android:title="@string/action_msg_info" /> android:title="@string/action_msg_info" />
<item <item
android:id="@+id/action_message_reply" android:id="@+id/action_message_reply"
android:icon="@drawable/ic_action_message_reply_24dp" android:icon="@drawable/ic_action_message_reply_24dp"
android:title="@string/action_msg_reply" /> android:title="@string/action_msg_reply" />
<item
android:id="@+id/action_message_edit"
android:icon="@drawable/ic_action_message_edit_24dp"
android:title="@string/action_msg_edit" />
<item
android:id="@+id/action_menu_msg_react"
android:icon="@drawable/ic_add_reaction"
android:title="@string/action_msg_add_reaction" />
<item <item
android:id="@+id/action_message_permalink" android:id="@+id/action_message_permalink"
...@@ -27,11 +34,6 @@ ...@@ -27,11 +34,6 @@
android:icon="@drawable/ic_action_message_copy_24dp" android:icon="@drawable/ic_action_message_copy_24dp"
android:title="@string/action_msg_copy" /> android:title="@string/action_msg_copy" />
<item
android:id="@+id/action_menu_msg_react"
android:icon="@drawable/ic_add_reaction"
android:title="@string/action_msg_add_reaction" />
<!--<item--> <!--<item-->
<!--android:id="@+id/action_menu_msg_share"--> <!--android:id="@+id/action_menu_msg_share"-->
<!--andrtextIconicon="@drawable/ic_share_black_24px"--> <!--andrtextIconicon="@drawable/ic_share_black_24px"-->
...@@ -48,9 +50,9 @@ ...@@ -48,9 +50,9 @@
android:title="@string/action_msg_pin" /> android:title="@string/action_msg_pin" />
<item <item
android:id="@+id/action_message_edit" android:id="@+id/action_message_report"
android:icon="@drawable/ic_action_message_edit_24dp" android:icon="@drawable/ic_action_message_report_24dp"
android:title="@string/action_msg_edit" /> android:title="@string/action_msg_report" />
<item <item
android:id="@+id/action_message_delete" android:id="@+id/action_message_delete"
......
...@@ -22,8 +22,12 @@ ...@@ -22,8 +22,12 @@
<string name="title_update_profile">Update Profil</string> <string name="title_update_profile">Update Profil</string>
<string name="title_about">Über</string> <string name="title_about">Über</string>
<string name="title_create_channel">Erstelle Raum</string> <string name="title_create_channel">Erstelle Raum</string>
<string name="title_are_you_sure">Are you sure?</string><!-- TODO Add translation -->
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation -->
<string name="title_topic">Thema</string>
<string name="title_announcement">Ankündigung</string>
<string name="title_description">Beschreibung</string>
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">Licence</string> <!-- TODO Add translation -->
<string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation -->
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Verbinde</string> <string name="action_connect">Verbinde</string>
...@@ -155,6 +159,9 @@ ...@@ -155,6 +159,9 @@
<string name="msg__your_2fa_code">What’s your 2FA code?</string> <!-- TODO Add translation --> <string name="msg__your_2fa_code">What’s your 2FA code?</string> <!-- TODO Add translation -->
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <string name="msg_muted_on_this_channel">You are muted on this channel</string>
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation -->
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation -->
<string name="msg_no_description">No description added</string> <!-- TODO Add translation -->
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <item quantity="one">%1$s reacted with %2$s</item>
...@@ -218,6 +225,8 @@ ...@@ -218,6 +225,8 @@
<string name="action_msg_add_reaction">Reaktion hinzufügen</string> <string name="action_msg_add_reaction">Reaktion hinzufügen</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Bearbeiten nicht erlaubt</string> <string name="permission_editing_not_allowed">Bearbeiten nicht erlaubt</string>
...@@ -322,5 +331,16 @@ ...@@ -322,5 +331,16 @@
<string name="notif_success_sending">Nachricht gesendet nach %1$s!</string> <string name="notif_success_sending">Nachricht gesendet nach %1$s!</string>
<string name="read_by">Gelesen von</string> <string name="read_by">Gelesen von</string>
<string name="message_information_title">Nachricht Information</string> <string name="message_information_title">Nachricht Information</string>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation--> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation-->
</resources>
\ No newline at end of file <!-- User Details -->
<string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources>
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
<string name="title_create_channel">Crear canal</string> <string name="title_create_channel">Crear canal</string>
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">Licence</string> <!-- TODO Add translation -->
<string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation --> <string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation -->
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation -->
<string name="title_topic">Tema</string>
<string name="title_announcement">Anuncio</string>
<string name="title_description">Descripción</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Conectar</string> <string name="action_connect">Conectar</string>
...@@ -171,6 +175,10 @@ ...@@ -171,6 +175,10 @@
<string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation --> <string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation -->
<string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation --> <string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation -->
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation --> <string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation -->
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation -->
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation -->
<string name="msg_no_description">No description added</string> <!-- TODO Add translation -->
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
<item quantity="other">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="other">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
...@@ -212,6 +220,8 @@ ...@@ -212,6 +220,8 @@
<string name="action_title_editing">Edición de mensaje</string> <string name="action_title_editing">Edición de mensaje</string>
<string name="action_msg_add_reaction">Añadir una reacción</string> <string name="action_msg_add_reaction">Añadir una reacción</string>
<string name="action_msg_copy_permalink">Copiar permalink</string> <string name="action_msg_copy_permalink">Copiar permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">La edición no és permitida</string> <string name="permission_editing_not_allowed">La edición no és permitida</string>
...@@ -322,7 +332,16 @@ ...@@ -322,7 +332,16 @@
<string name="msg_file_description">Descripción del archivo</string> <string name="msg_file_description">Descripción del archivo</string>
<string name="msg_send">Enviar</string> <string name="msg_send">Enviar</string>
<string name="msg_sent_attachment">Envió un archivo</string> <string name="msg_sent_attachment">Envió un archivo</string>
<!--TODO - Add proper translation--> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation-->
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources> </resources>
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
<string name="title_create_channel">Créer salon</string> <string name="title_create_channel">Créer salon</string>
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">Licence</string> <!-- TODO Add translation -->
<string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation --> <string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation -->
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation -->
<string name="title_topic">Sujet</string>
<string name="title_announcement">Annonce</string>
<string name="title_description">La description</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Se connecter</string> <string name="action_connect">Se connecter</string>
...@@ -163,6 +167,10 @@ ...@@ -163,6 +167,10 @@
<string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation --> <string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation -->
<string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation --> <string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation -->
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation --> <string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation -->
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation -->
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation -->
<string name="msg_no_description">No description added</string> <!-- TODO Add translation -->
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
<item quantity="other">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="other">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
...@@ -218,6 +226,8 @@ ...@@ -218,6 +226,8 @@
<string name="action_msg_add_reaction">Ajouter une réaction</string> <string name="action_msg_add_reaction">Ajouter une réaction</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">L\'édition n\'est pas autorisée</string> <string name="permission_editing_not_allowed">L\'édition n\'est pas autorisée</string>
...@@ -326,4 +336,15 @@ ...@@ -326,4 +336,15 @@
<string name="msg_sent_attachment">Envoyé un fichier</string> <string name="msg_sent_attachment">Envoyé un fichier</string>
<!--TODO - Add proper translation--> <!--TODO - Add proper translation-->
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string>
</resources>
\ No newline at end of file <!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string> <!-- TODO - Add proper translation -->
</resources>
...@@ -22,8 +22,12 @@ ...@@ -22,8 +22,12 @@
<string name="title_update_profile">प्रोफ़ाइल अपडेट करें</string> <string name="title_update_profile">प्रोफ़ाइल अपडेट करें</string>
<string name="title_about">परिचय</string> <string name="title_about">परिचय</string>
<string name="title_create_channel">चैनल बनाएं</string> <string name="title_create_channel">चैनल बनाएं</string>
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">लाइसेंस</string>
<string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation --> <string name="title_are_you_sure">क्या आपको यकीन है?</string>
<string name="title_channel_details">चैनल विवरण</string>
<string name="title_topic">विषय</string>
<string name="title_announcement">घोषणा</string>
<string name="title_description">विवरण</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">जुडिये</string> <string name="action_connect">जुडिये</string>
...@@ -36,7 +40,7 @@ ...@@ -36,7 +40,7 @@
<string name="action_create_channel">चैनल बनाएं</string> <string name="action_create_channel">चैनल बनाएं</string>
<string name="action_create">बनाएं</string> <string name="action_create">बनाएं</string>
<string name="action_logout">लोग आउट करें</string> <string name="action_logout">लोग आउट करें</string>
<string name="action_attach_a_files">Attach a file</string> <!-- TODO Add translation --> <string name="action_attach_a_files">एक फ़ाइल जोडो</string>
<string name="action_confirm_password">पासवर्ड परिवर्तन की पुष्टि करें</string> <string name="action_confirm_password">पासवर्ड परिवर्तन की पुष्टि करें</string>
<string name="action_join_chat">चैट में शामिल हों</string> <string name="action_join_chat">चैट में शामिल हों</string>
<string name="action_add_account">खाता जोड़ो</string> <string name="action_add_account">खाता जोड़ो</string>
...@@ -54,17 +58,17 @@ ...@@ -54,17 +58,17 @@
<string name="action_create_server">नया सर्वर बनाएं</string> <string name="action_create_server">नया सर्वर बनाएं</string>
<string name="action_register">रजिस्टर</string> <string name="action_register">रजिस्टर</string>
<string name="action_confirm">पुष्टि करें</string> <string name="action_confirm">पुष्टि करें</string>
<string name="action_delete_account">Delete account</string> <!-- TODO Add translation --> <string name="action_delete_account">खाता हटा दो</string>
<!-- Settings List --> <!-- Settings List -->
<string-array name="settings_actions"> <string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation --> <item name="item_preferences">पसंद</item>
<item name="item_password">Change password</item> <!-- TODO Add translation --> <item name="item_password">पासवर्ड बदलें</item>
<item name="item_share_app">Share app</item> <!-- TODO Add translation --> <item name="item_share_app">ऐप शेयर करें</item>
<item name="item_rate_us">Rate us</item> <!-- TODO Add translation --> <item name="item_rate_us">हमें रेटिंग दें</item>
<item name="item_contact_us">Contact us</item> <!-- TODO Add translation --> <item name="item_contact_us">हमसे संपर्क करें</item>
<item name="item_licence">Licence</item> <!-- TODO Add translation --> <item name="item_licence">लाइसेंस</item>
<item name="item_about">About</item> <!-- TODO Add translation --> <item name="item_about">के बारे में</item>
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
...@@ -173,14 +177,18 @@ ...@@ -173,14 +177,18 @@
<string name="msg_channel_created_successfully">चैनल सफलतापूर्वक बनाया गया</string> <string name="msg_channel_created_successfully">चैनल सफलतापूर्वक बनाया गया</string>
<string name="msg_view_more">और देखें</string> <string name="msg_view_more">और देखें</string>
<string name="msg_view_less">कम देखें</string> <string name="msg_view_less">कम देखें</string>
<string name="msg_permalink_copied">Permalink copied</string> <!-- TODO - Add proper translation --> <string name="msg_permalink_copied">पर्मलिंक की प्रतिलिपि बनाई गई</string>
<string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation --> <string name="msg_send_email">ईमेल भेजें</string>
<string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation --> <string name="msg_android_app_support">एंड्रॉइड ऐप समर्थन</string>
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation --> <string name="msg_muted_on_this_channel">आप इस चैनल पर म्यूट कर रहे हैं</string>
<string name="msg_no_topic">कोई विषय नहीं जोड़ा गया</string>
<string name="msg_no_announcement">कोई घोषणा नहीं जोड़ा गया</string>
<string name="msg_no_description">कोई विवरण नहीं जोड़ा गया</string>
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="one">% 1 $ s ने% 2 $ %d s के साथ प्रतिक्रिया व्यक्त की</item>
<item quantity="few">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="few">% 1 $ s ने% 2 $ s के साथ प्रतिक्रिया व्यक्त की</item>
<item quantity="many">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="many">% 1 $ s ने% 2 $ s के साथ प्रतिक्रिया व्यक्त की</item>
</plurals> </plurals>
<!-- Preferences messages --> <!-- Preferences messages -->
...@@ -218,8 +226,9 @@ ...@@ -218,8 +226,9 @@
<string name="action_msg_share">शेयर करें</string> <string name="action_msg_share">शेयर करें</string>
<string name="action_title_editing">संपादन संदेश</string> <string name="action_title_editing">संपादन संदेश</string>
<string name="action_msg_add_reaction">प्रतिक्रिया जोड़ें</string> <string name="action_msg_add_reaction">प्रतिक्रिया जोड़ें</string>
<string name="action_msg_copy_permalink">परमालिंक कॉपी करें</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">संपादन की अनुमति नहीं है</string> <string name="permission_editing_not_allowed">संपादन की अनुमति नहीं है</string>
...@@ -326,4 +335,15 @@ ...@@ -326,4 +335,15 @@
<string name="message_information_title">संदेश की जानकारी</string> <string name="message_information_title">संदेश की जानकारी</string>
<string name="msg_log_out">लॉग आउट कर रहा हूं…</string> <string name="msg_log_out">लॉग आउट कर रहा हूं…</string>
<string name="message_room_changed_privacy">%2$s ने रूम का प्रकार बदलकर %1$s किया </string> <string name="message_room_changed_privacy">%2$s ने रूम का प्रकार बदलकर %1$s किया </string>
<!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string>
</resources> </resources>
...@@ -22,8 +22,12 @@ ...@@ -22,8 +22,12 @@
<string name="title_update_profile">Aggiorna Profilo</string> <string name="title_update_profile">Aggiorna Profilo</string>
<string name="title_about">Informazioni</string> <string name="title_about">Informazioni</string>
<string name="title_create_channel">Crea Canale</string> <string name="title_create_channel">Crea Canale</string>
<string name="title_licence">Licence</string> <!-- TODO ADD translation --> <string name="title_licence">licenza</string>
<string name="title_are_you_sure">Sei sicuro che vuoi uscire ?</string> <string name="title_are_you_sure">Sei sicuro che vuoi uscire ?</string>
<string name="title_channel_details">Allegare un file</string>
<string name="title_topic">Argomento</string>
<string name="title_announcement">Annuncio</string>
<string name="title_description">Descrizione</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Collega</string> <string name="action_connect">Collega</string>
...@@ -36,7 +40,7 @@ ...@@ -36,7 +40,7 @@
<string name="action_create_channel">Crea canale</string> <string name="action_create_channel">Crea canale</string>
<string name="action_create">Crea</string> <string name="action_create">Crea</string>
<string name="action_logout">Disconnettersi</string> <string name="action_logout">Disconnettersi</string>
<string name="action_attach_a_files">Attach a file</string> <!-- TODO ADD translation --> <string name="action_attach_a_files">Ceangail comhad</string>
<string name="action_confirm_password">Conferma Cambio Password</string> <string name="action_confirm_password">Conferma Cambio Password</string>
<string name="action_join_chat">Iscriviti alla stanza</string> <string name="action_join_chat">Iscriviti alla stanza</string>
<string name="action_add_account">Aggiungi utente</string> <string name="action_add_account">Aggiungi utente</string>
...@@ -47,7 +51,7 @@ ...@@ -47,7 +51,7 @@
<string name="action_drawing">Disegno</string> <string name="action_drawing">Disegno</string>
<string name="action_save_to_gallery">Salva in galleria</string> <string name="action_save_to_gallery">Salva in galleria</string>
<string name="action_select_photo_from_gallery">Seleziona foto dalla galleria</string> <string name="action_select_photo_from_gallery">Seleziona foto dalla galleria</string>
<string name="action_take_a_photo">Take a photo</string> <!-- TODO ADD translation --> <string name="action_take_a_photo">Scatta una foto</string>
<string name="action_reset_avatar">Reimposta avatar</string> <string name="action_reset_avatar">Reimposta avatar</string>
<string name="action_connect_server">Collegati a un server</string> <string name="action_connect_server">Collegati a un server</string>
<string name="action_join_community">Entra nella community</string> <string name="action_join_community">Entra nella community</string>
...@@ -58,13 +62,13 @@ ...@@ -58,13 +62,13 @@
<!-- Settings List --> <!-- Settings List -->
<string-array name="settings_actions"> <string-array name="settings_actions">
<item name="item_preferences">Preferences</item> <!-- TODO Add translation --> <item name="item_preferences">Preferenze</item>
<item name="item_password">Change password</item> <!-- TODO Add translation --> <item name="item_password">Cambia password</item>
<item name="item_share_app">Share app</item> <!-- TODO Add translation --> <item name="item_share_app">Condividi app</item>
<item name="item_rate_us">Rate us</item> <!-- TODO Add translation --> <item name="item_rate_us">Votaci</item>
<item name="item_contact_us">Contact us</item> <!-- TODO Add translation --> <item name="item_contact_us">Contattaci</item>
<item name="item_licence">Licence</item> <!-- TODO Add translation --> <item name="item_licence">Licenza</item>
<item name="item_about">About</item> <!-- TODO Add translation --> <item name="item_about">Di</item>
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
...@@ -154,8 +158,12 @@ ...@@ -154,8 +158,12 @@
<string name="msg_two_factor_authentication">Autenticazione a 2 fattori (2FA)</string> <string name="msg_two_factor_authentication">Autenticazione a 2 fattori (2FA)</string>
<string name="msg__your_2fa_code">Qual è il tuo codice 2FA ?</string> <string name="msg__your_2fa_code">Qual è il tuo codice 2FA ?</string>
<string name="msg_permalink_copied">Permalink copiato</string> <string name="msg_permalink_copied">Permalink copiato</string>
<string name="msg_send_email">Send email</string> <string name="msg_no_topic">Nessun argomento aggiunto</string>
<string name="msg_android_app_support">Android app support</string> <string name="msg_no_announcement">Nessun annuncio aggiunto</string>
<string name="msg_no_description">Nessuna descrizione aggiunta</string>
<string name="msg_send_email">Invia una email</string>
<string name="msg_android_app_support">Supporto per le app Android</string>
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s ha reagito con %2$s</item> <item quantity="one">%1$s ha reagito con %2$s</item>
<item quantity="other">%1$s ha reagito con %2$s</item> <item quantity="other">%1$s ha reagito con %2$s</item>
...@@ -214,7 +222,9 @@ ...@@ -214,7 +222,9 @@
<string name="action_msg_share">Condividi</string> <string name="action_msg_share">Condividi</string>
<string name="action_title_editing">Modifica messaggio</string> <string name="action_title_editing">Modifica messaggio</string>
<string name="action_msg_add_reaction">Aggiungi reazione</string> <string name="action_msg_add_reaction">Aggiungi reazione</string>
<string name="action_msg_copy_permalink">Copia permalink</string>3 <string name="action_msg_copy_permalink">Copia permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">La modifica non è consentita</string> <string name="permission_editing_not_allowed">La modifica non è consentita</string>
...@@ -321,4 +331,14 @@ ...@@ -321,4 +331,14 @@
<string name="message_information_title">Informazioni Messaggio</string> <string name="message_information_title">Informazioni Messaggio</string>
<string name="message_room_changed_privacy">Il tipo di stanza è cambiato in: %1$s da %2$s</string> <string name="message_room_changed_privacy">Il tipo di stanza è cambiato in: %1$s da %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!-- TODO - Add proper translation -->
<string name="timezone">Timezone</string> <!-- TODO - Add proper translation -->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string> <!-- TODO - Add proper translation -->
</resources> </resources>
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">Licence</string> <!-- TODO Add translation -->
<string name="title_create_channel">新しいチャネルを作成</string> <string name="title_create_channel">新しいチャネルを作成</string>
<string name="title_are_you_sure">本気ですか?</string> <string name="title_are_you_sure">本気ですか?</string>
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation -->
<string name="title_topic">トピック</string>
<string name="title_announcement">発表</string>
<string name="title_description">説明</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">接続</string> <string name="action_connect">接続</string>
...@@ -161,6 +165,9 @@ ...@@ -161,6 +165,9 @@
<string name="msg_view_more">更に表示</string> <string name="msg_view_more">更に表示</string>
<string name="msg_view_less">隠す</string> <string name="msg_view_less">隠す</string>
<string name="msg_muted_on_this_channel">あなたはこのチャンネルでミュートされています</string> <string name="msg_muted_on_this_channel">あなたはこのチャンネルでミュートされています</string>
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation -->
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation -->
<string name="msg_no_description">No description added</string> <!-- TODO Add translation -->
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <item quantity="one">%1$s reacted with %2$s</item>
...@@ -221,6 +228,8 @@ ...@@ -221,6 +228,8 @@
<string name="action_title_editing">メッセージの編集</string> <string name="action_title_editing">メッセージの編集</string>
<string name="action_msg_add_reaction">リアクションする</string> <string name="action_msg_add_reaction">リアクションする</string>
<string name="action_msg_copy_permalink">パーマリンクのコピー</string> <string name="action_msg_copy_permalink">パーマリンクのコピー</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">編集は許可されていません</string> <string name="permission_editing_not_allowed">編集は許可されていません</string>
...@@ -329,4 +338,14 @@ ...@@ -329,4 +338,14 @@
<string name="message_room_changed_privacy">ルームタイプを %2$s から %1$s に変更しました</string> <string name="message_room_changed_privacy">ルームタイプを %2$s から %1$s に変更しました</string>
</resources> <!-- User Details -->
\ No newline at end of file <string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources>
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
<string name="title_create_channel">Criar chat</string> <string name="title_create_channel">Criar chat</string>
<string name="title_licence">Licença</string> <!-- TODO Add translation --> <string name="title_licence">Licença</string> <!-- TODO Add translation -->
<string name="title_are_you_sure">Você tem certeza?</string> <string name="title_are_you_sure">Você tem certeza?</string>
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation -->
<string name="title_topic">Tópico</string>
<string name="title_announcement">Anúncio</string>
<string name="title_description">Descrição</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Conectar</string> <string name="action_connect">Conectar</string>
...@@ -164,6 +168,9 @@ ...@@ -164,6 +168,9 @@
<string name="msg_send_email">Enviar e-mail</string> <string name="msg_send_email">Enviar e-mail</string>
<string name="msg_android_app_support">Suporte ao aplicativo Android</string> <string name="msg_android_app_support">Suporte ao aplicativo Android</string>
<string name="msg_muted_on_this_channel">Você está silenciado neste canal</string> <string name="msg_muted_on_this_channel">Você está silenciado neste canal</string>
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation -->
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation -->
<string name="msg_no_description">No description added</string> <!-- TODO Add translation -->
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reagiu com %2$s</item> <item quantity="one">%1$s reagiu com %2$s</item>
<item quantity="other">%1$s reagiram com %2$s</item> <item quantity="other">%1$s reagiram com %2$s</item>
...@@ -218,6 +225,8 @@ ...@@ -218,6 +225,8 @@
<string name="action_title_editing">Editando mensagem</string> <string name="action_title_editing">Editando mensagem</string>
<string name="action_msg_add_reaction">Adicionar reação</string> <string name="action_msg_add_reaction">Adicionar reação</string>
<string name="action_msg_copy_permalink">Copiar permalink</string> <string name="action_msg_copy_permalink">Copiar permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Reportar</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Edição não permitida</string> <string name="permission_editing_not_allowed">Edição não permitida</string>
...@@ -325,4 +334,15 @@ ...@@ -325,4 +334,15 @@
<string name="msg_log_out">Deslogando…</string> <string name="msg_log_out">Deslogando…</string>
<string name="msg_sent_attachment">Enviou um arquivo</string> <string name="msg_sent_attachment">Enviou um arquivo</string>
<string name="message_room_changed_privacy">O tipo da sala mudou para: %1$s por %2$s</string> <string name="message_room_changed_privacy">O tipo da sala mudou para: %1$s por %2$s</string>
<!-- User Details -->
<string name="message">Mensagem</string>
<string name="timezone">Fuso horário</string>
<string name="error_opening_dm">Algo deu errado quando tentamos abrir esta conversa…</string>
<string name="retry">Retentar</string>
<!-- Report -->
<string name="submit">Enviar</string>
<string name="required">*obrigatório</string>
<string name="report_sent">A mensagem foi reportada!</string>
</resources> </resources>
...@@ -22,6 +22,10 @@ ...@@ -22,6 +22,10 @@
<string name="title_update_profile">Обновить профиль</string> <string name="title_update_profile">Обновить профиль</string>
<string name="title_about">О программе</string> <string name="title_about">О программе</string>
<string name="title_create_channel">Создать новый канал</string> <string name="title_create_channel">Создать новый канал</string>
<string name="title_channel_details">О канале</string>
<string name="title_topic">Тема</string>
<string name="title_announcement">Объявление</string>
<string name="title_description">Описание</string>
<string name="title_licence">Лицензия</string> <string name="title_licence">Лицензия</string>
<string name="title_are_you_sure">Вы уверены?</string> <string name="title_are_you_sure">Вы уверены?</string>
...@@ -159,9 +163,13 @@ ...@@ -159,9 +163,13 @@
<string name="msg_view_more">больше</string> <string name="msg_view_more">больше</string>
<string name="msg_view_less">меньше</string> <string name="msg_view_less">меньше</string>
<string name="msg_permalink_copied">Ссылка скопирована</string> <string name="msg_permalink_copied">Ссылка скопирована</string>
<string name="msg_no_topic">Нет темы</string>
<string name="msg_no_announcement">Нет объявления</string>
<string name="msg_no_description">Нет описания</string>
<string name="msg_send_email">Отправить e-mail</string> <string name="msg_send_email">Отправить e-mail</string>
<string name="msg_android_app_support">Поддержка Android-приложения</string> <string name="msg_android_app_support">Поддержка Android-приложения</string>
<string name="msg_muted_on_this_channel">Вы лишены дара речи на этом канале</string> <string name="msg_muted_on_this_channel">Вы лишены дара речи на этом канале</string>
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s реагирует с %2$s</item> <item quantity="one">%1$s реагирует с %2$s</item>
<item quantity="few">%1$s реагируют с %2$s</item> <item quantity="few">%1$s реагируют с %2$s</item>
...@@ -216,6 +224,8 @@ ...@@ -216,6 +224,8 @@
<string name="action_title_editing">Редактирование сообщения</string> <string name="action_title_editing">Редактирование сообщения</string>
<string name="action_msg_add_reaction">Отреагировать</string> <string name="action_msg_add_reaction">Отреагировать</string>
<string name="action_msg_copy_permalink">Копировать ссылку</string> <string name="action_msg_copy_permalink">Копировать ссылку</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Редактирование запрещено</string> <string name="permission_editing_not_allowed">Редактирование запрещено</string>
...@@ -322,4 +332,15 @@ ...@@ -322,4 +332,15 @@
<string name="message_information_title">Информация о прочтении</string> <string name="message_information_title">Информация о прочтении</string>
<string name="msg_log_out">Выходим…</string> <string name="msg_log_out">Выходим…</string>
<string name="message_room_changed_privacy">Тип канала изменен на: %1$s пользователем %2$s</string> <string name="message_room_changed_privacy">Тип канала изменен на: %1$s пользователем %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources> </resources>
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
<string name="title_create_channel">Yeni Kanal Oluştur</string> <string name="title_create_channel">Yeni Kanal Oluştur</string>
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">Licence</string> <!-- TODO Add translation -->
<string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation --> <string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation -->
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation -->
<string name="title_topic">konu</string>
<string name="title_announcement">duyuru</string>
<string name="title_description">Açıklama</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Bağlan</string> <string name="action_connect">Bağlan</string>
...@@ -178,10 +182,15 @@ ...@@ -178,10 +182,15 @@
<string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation --> <string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation -->
<string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation --> <string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation -->
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation --> <string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation -->
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation -->
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation -->
<string name="msg_no_description">No description added</string> <!-- TODO Add translation -->
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
<item quantity="other">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="other">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
</plurals> </plurals>
<!-- Preferences messages --> <!-- Preferences messages -->
<string name="msg_analytics_tracking">İstatistik takibi</string> <string name="msg_analytics_tracking">İstatistik takibi</string>
<string name="msg_send_analytics_tracking">Uygulamanın gelişmesine katkıda bulunmak için anonim istatistik bilgisi gönder</string> <string name="msg_send_analytics_tracking">Uygulamanın gelişmesine katkıda bulunmak için anonim istatistik bilgisi gönder</string>
...@@ -219,6 +228,8 @@ ...@@ -219,6 +228,8 @@
<string name="action_msg_add_reaction">Tepki Ekle</string> <string name="action_msg_add_reaction">Tepki Ekle</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Düzenlemeye izin verilmiyor</string> <string name="permission_editing_not_allowed">Düzenlemeye izin verilmiyor</string>
...@@ -323,7 +334,16 @@ ...@@ -323,7 +334,16 @@
<string name="notif_success_sending">Mesaj %1$s\'a gönderildi!</string> <string name="notif_success_sending">Mesaj %1$s\'a gönderildi!</string>
<string name="read_by">ile oku</string> <string name="read_by">ile oku</string>
<string name="message_information_title">Mesaj bilgisi</string> <string name="message_information_title">Mesaj bilgisi</string>
<!--TODO - Add proper translation--> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!--TODO - Add proper translation-->
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string>
<!-- User Details -->
<string name="message">Message</string> <!--TODO - Add proper translation-->
<string name="timezone">Timezone</string> <!--TODO - Add proper translation-->
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!--TODO - Add proper translation-->
<string name="required">*required</string> <!--TODO - Add proper translation-->
<string name="report_sent">Your report has been sent!</string> <!--TODO - Add proper translation-->
</resources> </resources>
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
<string name="title_create_channel">Створити новий канал</string> <string name="title_create_channel">Створити новий канал</string>
<string name="title_licence">Licence</string> <!-- TODO Add translation --> <string name="title_licence">Licence</string> <!-- TODO Add translation -->
<string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation --> <string name="title_are_you_sure">Are you sure?</string> <!-- TODO Add translation -->
<string name="title_channel_details">Channel Details</string> <!-- TODO add translation -->
<string name="title_topic">Тема</string>
<string name="title_announcement">Оголошення</string>
<string name="title_description">Опис</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Підключитися</string> <string name="action_connect">Підключитися</string>
...@@ -161,6 +165,10 @@ ...@@ -161,6 +165,10 @@
<string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation --> <string name="msg_send_email">Send email</string> <!-- TODO - Add proper translation -->
<string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation --> <string name="msg_android_app_support">Android app support</string> <!-- TODO - Add proper translation -->
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation --> <string name="msg_muted_on_this_channel">You are muted on this channel</string> <!-- TODO - Add proper translation -->
<string name="msg_no_topic">No topic added</string> <!-- TODO Add translation -->
<string name="msg_no_announcement">No announcement added</string> <!-- TODO Add translation -->
<string name="msg_no_description">No description added</string> <!-- TODO Add translation -->
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="one">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
<item quantity="few">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation --> <item quantity="few">%1$s reacted with %2$s</item> <!-- TODO - Add proper translation -->
...@@ -216,6 +224,8 @@ ...@@ -216,6 +224,8 @@
<string name="action_msg_add_reaction">Відреагувати</string> <string name="action_msg_add_reaction">Відреагувати</string>
<!-- TODO - Add proper translation --> <!-- TODO - Add proper translation -->
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<!-- TODO - Add proper translation -->
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Редагування заборонено</string> <string name="permission_editing_not_allowed">Редагування заборонено</string>
...@@ -322,6 +332,16 @@ ...@@ -322,6 +332,16 @@
<string name="message_information_title">Інформація про прочитання</string> <string name="message_information_title">Інформація про прочитання</string>
<string name="msg_log_out">Виходимо…</string> <string name="msg_log_out">Виходимо…</string>
<string name="msg_sent_attachment">Долучення відправлено</string> <string name="msg_sent_attachment">Долучення відправлено</string>
<!--TODO - Add proper translation--> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <!-- TODO - Add proper translation -->
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string>
<!-- User Details -->
<string name="message">Message</string>
<string name="timezone">Timezone</string>
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string> <!-- TODO - Add proper translation -->
<string name="retry">Retry</string> <!-- TODO - Add proper translation -->
<!-- Report -->
<string name="submit">Submit</string> <!-- TODO - Add proper translation -->
<string name="required">*required</string> <!-- TODO - Add proper translation -->
<string name="report_sent">Your report has been sent!</string> <!-- TODO - Add proper translation -->
</resources> </resources>
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
<color name="colorPrimaryText">#DE000000</color> <color name="colorPrimaryText">#DE000000</color>
<color name="colorSecondaryText">#FF787878</color> <color name="colorSecondaryText">#FF787878</color>
<color name="colorSecondaryTextLight">#FFC1C1C1</color> <color name="colorSecondaryTextLight">#FFC1C1C1</color>
<color name="colorTimestampText">#FF9DA2A9</color>
<color name="colorTimestampTextUnread">#FF5699FF</color>
<color name="colorLastMessageText">#99000000</color>
<!-- User status colors --> <!-- User status colors -->
<color name="colorUserStatusOnline">#2FE1A8</color> <color name="colorUserStatusOnline">#2FE1A8</color>
...@@ -52,6 +55,8 @@ ...@@ -52,6 +55,8 @@
<color name="colorDivider">#1F000000</color> <color name="colorDivider">#1F000000</color>
<color name="colorLightGrey">#F4F5F7</color>
<!-- Suggestions --> <!-- Suggestions -->
<color name="suggestion_background_color">@color/colorWhite</color> <color name="suggestion_background_color">@color/colorWhite</color>
......
...@@ -36,6 +36,10 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -36,6 +36,10 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="title_create_channel">Create Channel</string> <string name="title_create_channel">Create Channel</string>
<string name="title_licence">Licence</string> <string name="title_licence">Licence</string>
<string name="title_are_you_sure">Are you sure?</string> <string name="title_are_you_sure">Are you sure?</string>
<string name="title_channel_details">Channel Details</string>
<string name="title_topic">Topic</string>
<string name="title_announcement">Announcement</string>
<string name="title_description">Description</string>
<!-- Actions --> <!-- Actions -->
<string name="action_connect">Connect</string> <string name="action_connect">Connect</string>
...@@ -171,8 +175,12 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -171,8 +175,12 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="msg_two_factor_authentication">Two-factor Authentication</string> <string name="msg_two_factor_authentication">Two-factor Authentication</string>
<string name="msg__your_2fa_code">What’s your 2FA code?</string> <string name="msg__your_2fa_code">What’s your 2FA code?</string>
<string name="msg_permalink_copied">Permalink copied</string> <string name="msg_permalink_copied">Permalink copied</string>
<string name="msg_no_topic">No topic added</string>
<string name="msg_no_announcement">No announcement added</string>
<string name="msg_no_description">No description added</string>
<string name="msg_send_email">Send email</string> <string name="msg_send_email">Send email</string>
<string name="msg_android_app_support">Android app support</string> <string name="msg_android_app_support">Android app support</string>
<plurals name="msg_reacted_with_"> <plurals name="msg_reacted_with_">
<item quantity="one">%1$s reacted with %2$s</item> <item quantity="one">%1$s reacted with %2$s</item>
<item quantity="other">%1$s reacted with %2$s</item> <item quantity="other">%1$s reacted with %2$s</item>
...@@ -195,7 +203,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -195,7 +203,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="msg_view_more">view more</string> <string name="msg_view_more">view more</string>
<string name="msg_view_less">view less</string> <string name="msg_view_less">view less</string>
<string name="msg_muted_on_this_channel">You are muted on this channel</string> <string name="msg_muted_on_this_channel">You are muted on this channel</string>
<!-- Preferences messages --> <!-- Preferences messages -->
<string name="msg_analytics_tracking">Analytics tracking</string> <string name="msg_analytics_tracking">Analytics tracking</string>
<string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string> <string name="msg_send_analytics_tracking">Send anonymous statics to help improving this app</string>
...@@ -232,6 +240,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -232,6 +240,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="action_title_editing">Editing Message</string> <string name="action_title_editing">Editing Message</string>
<string name="action_msg_add_reaction">Add reaction</string> <string name="action_msg_add_reaction">Add reaction</string>
<string name="action_msg_copy_permalink">Copy permalink</string> <string name="action_msg_copy_permalink">Copy permalink</string>
<string name="action_msg_report">Report</string>
<!-- Permission messages --> <!-- Permission messages -->
<string name="permission_editing_not_allowed">Editing is not allowed</string> <string name="permission_editing_not_allowed">Editing is not allowed</string>
...@@ -338,5 +347,17 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin ...@@ -338,5 +347,17 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="message_information_title">Message information</string> <string name="message_information_title">Message information</string>
<string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string> <string name="message_room_changed_privacy">Room type changed to: %1$s by %2$s</string>
<string name="foss" tools:ignore="MissingTranslation">(FOSS)</string> <string name="foss" translatable="false">(FOSS)</string>
</resources>
\ No newline at end of file <!-- User Details -->
<string name="message">Message</string>
<string name="timezone">Timezone</string>
<string name="status" translatable="false">Status</string>
<string name="error_opening_dm">Something went wrong while we were creating this conversation…</string>
<string name="retry">Retry</string>
<!-- Report -->
<string name="submit">Submit</string>
<string name="required">*required</string>
<string name="report_sent">Your report has been sent!</string>
</resources>
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
<item name="android:layout_width">wrap_content</item> <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:textSize">24sp</item> <item name="android:textSize">24sp</item>
<item name="android:lineSpacingExtra">4sp</item>
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textColor">@color/colorPrimary</item> <item name="android:textColor">@color/colorPrimary</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
...@@ -29,7 +28,6 @@ ...@@ -29,7 +28,6 @@
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:lineSpacingExtra">4sp</item>
<item name="android:textColor">#FF54585E</item> <item name="android:textColor">#FF54585E</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
</style> </style>
...@@ -39,7 +37,6 @@ ...@@ -39,7 +37,6 @@
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
<item name="android:textColor">@color/colorAccent</item> <item name="android:textColor">@color/colorAccent</item>
<item name="android:letterSpacing">0.04</item>
<item name="android:maxLines">1</item> <item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item> <item name="android:ellipsize">end</item>
</style> </style>
...@@ -53,7 +50,6 @@ ...@@ -53,7 +50,6 @@
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorAuthenticationSecondaryText</item> <item name="android:textColor">@color/colorAuthenticationSecondaryText</item>
<item name="android:letterSpacing">0.04</item>
<item name="android:maxLines">1</item> <item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item> <item name="android:ellipsize">end</item>
</style> </style>
...@@ -63,7 +59,6 @@ ...@@ -63,7 +59,6 @@
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
<item name="android:textColorHint">@color/colorAuthenticationSecondaryText</item> <item name="android:textColorHint">@color/colorAuthenticationSecondaryText</item>
<item name="android:lineSpacingExtra">3sp</item>
</style> </style>
<style name="Authentication.EditText.Border" parent="Widget.AppCompat.EditText"> <style name="Authentication.EditText.Border" parent="Widget.AppCompat.EditText">
...@@ -87,7 +82,6 @@ ...@@ -87,7 +82,6 @@
<item name="android:fontFamily">sans-serif-medium</item> <item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item> <item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorWhite</item> <item name="android:textColor">@color/colorWhite</item>
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>
<item name="android:background">@drawable/rounded_color_accent</item> <item name="android:background">@drawable/rounded_color_accent</item>
</style> </style>
...@@ -100,15 +94,66 @@ ...@@ -100,15 +94,66 @@
<item name="android:textSize">18sp</item> <item name="android:textSize">18sp</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
<item name="android:fontFamily">sans-serif</item> <item name="android:fontFamily">sans-serif</item>
<item name="android:lineSpacingExtra">2sp</item>
</style> </style>
// REMARK: To be removed as soon as we have our loading view.
<style name="Authentication.AVLoadingIndicatorView" parent="AVLoadingIndicatorView"> <style name="Authentication.AVLoadingIndicatorView" parent="AVLoadingIndicatorView">
<item name="android:layout_width">wrap_content</item> <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="indicatorColor">@color/colorPrimary</item> <item name="indicatorColor">@color/colorPrimary</item>
<item name="indicatorName">BallPulseIndicator</item> <item name="indicatorName">BallPulseIndicator</item>
</style> </style>
<!-- End Authentication -->
<!-- Chat list -->
<style name="ChatList.ChatName.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">16sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
</style>
<style name="ChatList.ChatName.Unread.TextView" parent="ChatList.ChatName.TextView">
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">bold</item>
</style>
<style name="ChatList.LastMessage.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorLastMessageText</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
</style>
<style name="ChatList.LastMessage.Unread.TextView" parent="ChatList.LastMessage.TextView">
<item name="android:fontFamily">sans-serif-medium</item>
</style>
<style name="ChatList.Timestamp.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">12sp</item>
<item name="android:fontFamily">sans-serif</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorTimestampText</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
</style>
<style name="ChatList.Timestamp.Unread.TextView" parent="ChatList.Timestamp.TextView">
<item name="android:textColor">@color/colorTimestampTextUnread</item>
</style>
<style name="ChatList.Badge.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@color/colorWhite</item>
<item name="android:gravity">center</item>
</style>
<!-- End chat list -->
<style name="EditText.Password" parent="TextAppearance.AppCompat"> <style name="EditText.Password" parent="TextAppearance.AppCompat">
<!-- Hint color and label color in FALSE state --> <!-- Hint color and label color in FALSE state -->
...@@ -118,13 +163,6 @@ ...@@ -118,13 +163,6 @@
<item name="colorControlActivated">@color/colorPrimaryDark</item> <item name="colorControlActivated">@color/colorPrimaryDark</item>
</style> </style>
<style name="AuthenticationLabel" parent="TextAppearance.AppCompat.Medium">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">50dp</item>
<item name="android:layout_marginStart">@dimen/screen_edge_left_and_right_margins</item>
<item name="android:paddingStart">@dimen/edit_text_margin</item>
</style>
<style name="ChatRoom.SearchView" parent="Widget.AppCompat.SearchView"> <style name="ChatRoom.SearchView" parent="Widget.AppCompat.SearchView">
<item name="queryHint">@string/title_search_message</item> <item name="queryHint">@string/title_search_message</item>
<item name="searchIcon">@drawable/ic_search_white_24dp</item> <item name="searchIcon">@drawable/ic_search_white_24dp</item>
...@@ -132,14 +170,22 @@ ...@@ -132,14 +170,22 @@
<item name="closeIcon">@drawable/ic_close_white_24dp</item> <item name="closeIcon">@drawable/ic_close_white_24dp</item>
</style> </style>
<style name="ChatRoom.Timestamp.TextView" parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">10sp</item>
</style>
<style name="ChatRooms.Header" parent="TextAppearance.AppCompat.Headline"> <style name="ChatRooms.Header" parent="TextAppearance.AppCompat.Headline">
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
</style> </style>
<style name="ChatRoom.Name.TextView" parent="TextAppearance.AppCompat.Title"> <style name="ChatDetails.Title.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="android:textColor">@color/colorPrimary</item>
</style>
<style name="ChatDetails.Content.TextView" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">12sp</item>
<item name="android:textColor">@color/colorSecondaryTextLight</item>
</style> </style>
<style name="Sender.Name.TextView" parent="TextAppearance.AppCompat.Title"> <style name="Sender.Name.TextView" parent="TextAppearance.AppCompat.Title">
...@@ -163,10 +209,6 @@ ...@@ -163,10 +209,6 @@
<item name="android:textColor">@color/colorPrimaryText</item> <item name="android:textColor">@color/colorPrimaryText</item>
</style> </style>
<style name="Timestamp.TextView" parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">10sp</item>
</style>
// REMARK: To be removed. // REMARK: To be removed.
<style name="Profile.EditText" parent="Authentication.EditText.Border"> <style name="Profile.EditText" parent="Authentication.EditText.Border">
<item name="android:background">@drawable/style_edit_text_profile</item> <item name="android:background">@drawable/style_edit_text_profile</item>
......
...@@ -26,7 +26,7 @@ ext { ...@@ -26,7 +26,7 @@ ext {
playServices : '16.0.0', playServices : '16.0.0',
exoPlayer : '2.8.2', exoPlayer : '2.8.2',
flexbox : '1.1.0', flexbox : '1.1.0',
material : '1.0.0-beta01', material : '1.0.0',
room : '2.0.0', room : '2.0.0',
lifecycle : '2.0.0', lifecycle : '2.0.0',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment