Skip to content
This repository was archived by the owner on Jun 7, 2020. It is now read-only.

Commit 1bb668c

Browse files
authored
Merge pull request #1364 from RocketChat/beta
[RELEASE] Merge beta into master
2 parents 72fb3e0 + 612f67b commit 1bb668c

46 files changed

Lines changed: 661 additions & 43 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ android {
1313
applicationId "chat.rocket.android"
1414
minSdkVersion 21
1515
targetSdkVersion versions.targetSdk
16-
versionCode 2026
17-
versionName "2.3.2"
16+
versionCode 2027
17+
versionName "2.4.0"
1818
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
1919
multiDexEnabled true
2020
}
@@ -54,6 +54,7 @@ android {
5454

5555
packagingOptions {
5656
exclude 'META-INF/core.kotlin_module'
57+
exclude 'META-INF/main.kotlin_module'
5758
}
5859
}
5960

app/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@
7474
android:theme="@style/AppTheme"
7575
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
7676

77+
<activity
78+
android:name=".chatinformation.ui.MessageInfoActivity"
79+
android:theme="@style/AppTheme"
80+
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
81+
7782
<!-- TODO: Change to fragment-->
7883
<activity
7984
android:name=".settings.password.ui.PasswordActivity"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package chat.rocket.android.chatinformation.adapter
2+
3+
import android.support.v7.widget.RecyclerView
4+
import android.view.View
5+
import android.view.ViewGroup
6+
import chat.rocket.android.R
7+
import chat.rocket.android.chatinformation.adapter.ReadReceiptAdapter.ReadReceiptViewHolder
8+
import chat.rocket.android.chatinformation.viewmodel.ReadReceiptViewModel
9+
import chat.rocket.android.util.extensions.inflate
10+
import kotlinx.android.synthetic.main.avatar.view.*
11+
import kotlinx.android.synthetic.main.item_read_receipt.view.*
12+
13+
class ReadReceiptAdapter : RecyclerView.Adapter<ReadReceiptViewHolder>() {
14+
private val data = ArrayList<ReadReceiptViewModel>()
15+
16+
init {
17+
setHasStableIds(true)
18+
}
19+
20+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReadReceiptViewHolder {
21+
return ReadReceiptViewHolder(parent.inflate(R.layout.item_read_receipt, false))
22+
}
23+
24+
override fun getItemCount(): Int {
25+
return data.size
26+
}
27+
28+
override fun onBindViewHolder(holder: ReadReceiptViewHolder, position: Int) {
29+
holder.bind(data[position])
30+
}
31+
32+
fun addAll(items: List<ReadReceiptViewModel>) {
33+
data.clear()
34+
data.addAll(items)
35+
notifyItemRangeInserted(0, items.size)
36+
}
37+
38+
class ReadReceiptViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
39+
40+
fun bind(readReceipt: ReadReceiptViewModel) {
41+
with(itemView) {
42+
image_avatar.setImageURI(readReceipt.avatar)
43+
receipt_name.text = readReceipt.name
44+
receipt_time.text = readReceipt.time
45+
}
46+
}
47+
}
48+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package chat.rocket.android.chatinformation.di
2+
3+
import android.arch.lifecycle.LifecycleOwner
4+
import chat.rocket.android.chatinformation.presentation.MessageInfoView
5+
import chat.rocket.android.chatinformation.ui.MessageInfoFragment
6+
import chat.rocket.android.core.lifecycle.CancelStrategy
7+
import chat.rocket.android.dagger.scope.PerFragment
8+
import dagger.Module
9+
import dagger.Provides
10+
import kotlinx.coroutines.experimental.Job
11+
12+
@Module
13+
@PerFragment
14+
class MessageInfoFragmentModule {
15+
16+
@Provides
17+
fun messageInfoView(frag: MessageInfoFragment): MessageInfoView {
18+
return frag
19+
}
20+
21+
@Provides
22+
fun provideLifecycleOwner(frag: MessageInfoFragment): LifecycleOwner {
23+
return frag
24+
}
25+
26+
@Provides
27+
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
28+
return CancelStrategy(owner, jobs)
29+
}
30+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package chat.rocket.android.chatinformation.di
2+
3+
import chat.rocket.android.chatinformation.ui.MessageInfoFragment
4+
import chat.rocket.android.dagger.scope.PerFragment
5+
import dagger.Module
6+
import dagger.android.ContributesAndroidInjector
7+
8+
@Module
9+
abstract class MessageInfoFragmentProvider {
10+
11+
@ContributesAndroidInjector(modules = [MessageInfoFragmentModule::class])
12+
@PerFragment
13+
abstract fun provideMessageInfoFragment(): MessageInfoFragment
14+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package chat.rocket.android.chatinformation.presentation
2+
3+
import chat.rocket.android.chatinformation.viewmodel.ReadReceiptViewModel
4+
import chat.rocket.android.chatroom.viewmodel.ViewModelMapper
5+
import chat.rocket.android.core.lifecycle.CancelStrategy
6+
import chat.rocket.android.helper.UserHelper
7+
import chat.rocket.android.server.domain.GetCurrentServerInteractor
8+
import chat.rocket.android.server.domain.MessagesRepository
9+
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
10+
import chat.rocket.android.util.extensions.launchUI
11+
import chat.rocket.android.util.retryIO
12+
import chat.rocket.common.RocketChatException
13+
import chat.rocket.core.internal.rest.getMessageReadReceipts
14+
import chat.rocket.core.internal.rest.queryUsers
15+
import timber.log.Timber
16+
import javax.inject.Inject
17+
18+
class MessageInfoPresenter @Inject constructor(
19+
private val view: MessageInfoView,
20+
private val strategy: CancelStrategy,
21+
private val mapper: ViewModelMapper,
22+
serverInteractor: GetCurrentServerInteractor,
23+
factory: ConnectionManagerFactory
24+
) {
25+
26+
private val currentServer = serverInteractor.get()!!
27+
private val manager = factory.create(currentServer)
28+
private val client = manager.client
29+
30+
fun loadReadReceipts(messageId: String) {
31+
launchUI(strategy) {
32+
try {
33+
view.showLoading()
34+
val readReceipts = retryIO(description = "getMessageReadReceipts") {
35+
client.getMessageReadReceipts(messageId = messageId).result
36+
}
37+
view.showReadReceipts(mapper.map(readReceipts))
38+
} catch (ex: RocketChatException) {
39+
Timber.e(ex)
40+
view.showGenericErrorMessage()
41+
} finally {
42+
view.hideLoading()
43+
}
44+
}
45+
}
46+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package chat.rocket.android.chatinformation.presentation
2+
3+
import chat.rocket.android.chatinformation.viewmodel.ReadReceiptViewModel
4+
import chat.rocket.android.core.behaviours.LoadingView
5+
6+
interface MessageInfoView : LoadingView {
7+
8+
fun showGenericErrorMessage()
9+
10+
fun showReadReceipts(messageReceipts: List<ReadReceiptViewModel>)
11+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package chat.rocket.android.chatinformation.ui
2+
3+
import android.content.Context
4+
import android.content.Intent
5+
import android.os.Bundle
6+
import android.support.v4.app.Fragment
7+
import android.support.v7.app.AppCompatActivity
8+
import chat.rocket.android.R
9+
import chat.rocket.android.chatinformation.ui.MessageInfoFragment.Companion.TAG_MESSAGE_INFO_FRAGMENT
10+
import chat.rocket.android.util.extensions.addFragment
11+
import chat.rocket.android.util.extensions.textContent
12+
import dagger.android.AndroidInjection
13+
import dagger.android.AndroidInjector
14+
import dagger.android.DispatchingAndroidInjector
15+
import dagger.android.support.HasSupportFragmentInjector
16+
import kotlinx.android.synthetic.main.app_bar_chat_room.*
17+
import javax.inject.Inject
18+
19+
fun Context.messageInformationIntent(messageId: String): Intent {
20+
return Intent(this, MessageInfoActivity::class.java).apply {
21+
putExtra(INTENT_MESSAGE_ID, messageId)
22+
}
23+
}
24+
25+
private const val INTENT_MESSAGE_ID = "message_id"
26+
27+
class MessageInfoActivity : AppCompatActivity(), HasSupportFragmentInjector {
28+
29+
@Inject
30+
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
31+
32+
override fun onCreate(savedInstanceState: Bundle?) {
33+
AndroidInjection.inject(this)
34+
super.onCreate(savedInstanceState)
35+
setContentView(R.layout.activity_chat_room)
36+
setupToolbar()
37+
38+
val messageId = intent.getStringExtra(INTENT_MESSAGE_ID)
39+
requireNotNull(messageId) { "no message_id provided in Intent extras" }
40+
41+
if (supportFragmentManager.findFragmentByTag(TAG_MESSAGE_INFO_FRAGMENT) == null) {
42+
addFragment(TAG_MESSAGE_INFO_FRAGMENT, R.id.fragment_container) {
43+
newInstance(messageId = messageId)
44+
}
45+
}
46+
}
47+
48+
private fun setupToolbar() {
49+
text_room_name.textContent = getString(R.string.message_information_title)
50+
setSupportActionBar(toolbar)
51+
supportActionBar?.setDisplayShowTitleEnabled(false)
52+
toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
53+
toolbar.setNavigationOnClickListener { finishActivity() }
54+
}
55+
56+
private fun finishActivity() {
57+
super.onBackPressed()
58+
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
59+
}
60+
61+
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
62+
return fragmentDispatchingAndroidInjector
63+
}
64+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package chat.rocket.android.chatinformation.ui
2+
3+
import android.os.Bundle
4+
import android.support.v4.app.Fragment
5+
import android.support.v7.widget.DefaultItemAnimator
6+
import android.support.v7.widget.LinearLayoutManager
7+
import android.support.v7.widget.RecyclerView
8+
import android.view.LayoutInflater
9+
import android.view.View
10+
import android.view.ViewGroup
11+
import chat.rocket.android.R
12+
import chat.rocket.android.chatinformation.adapter.ReadReceiptAdapter
13+
import chat.rocket.android.chatinformation.presentation.MessageInfoPresenter
14+
import chat.rocket.android.chatinformation.presentation.MessageInfoView
15+
import chat.rocket.android.chatinformation.viewmodel.ReadReceiptViewModel
16+
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
17+
import chat.rocket.android.util.extensions.setVisible
18+
import chat.rocket.android.util.extensions.showToast
19+
import chat.rocket.core.model.ReadReceipt
20+
import dagger.android.support.AndroidSupportInjection
21+
import kotlinx.android.synthetic.main.fragment_message_info.*
22+
import javax.inject.Inject
23+
24+
fun newInstance(messageId: String): Fragment {
25+
return MessageInfoFragment().apply {
26+
arguments = Bundle(1).apply {
27+
putString(BUNDLE_MESSAGE_ID, messageId)
28+
}
29+
}
30+
}
31+
32+
private const val BUNDLE_MESSAGE_ID = "message_id"
33+
34+
class MessageInfoFragment : Fragment(), MessageInfoView {
35+
36+
@Inject
37+
lateinit var presenter: MessageInfoPresenter
38+
39+
private lateinit var adapter: ReadReceiptAdapter
40+
private lateinit var endlessRecyclerViewScrollListener: EndlessRecyclerViewScrollListener
41+
private lateinit var messageId: String
42+
43+
override fun onCreate(savedInstanceState: Bundle?) {
44+
super.onCreate(savedInstanceState)
45+
AndroidSupportInjection.inject(this)
46+
setHasOptionsMenu(true)
47+
48+
val bundle = arguments
49+
if (bundle != null) {
50+
messageId = bundle.getString(BUNDLE_MESSAGE_ID)
51+
} else {
52+
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
53+
}
54+
}
55+
56+
override fun onCreateView(
57+
inflater: LayoutInflater,
58+
container: ViewGroup?,
59+
savedInstanceState: Bundle?
60+
): View {
61+
return inflater.inflate(R.layout.fragment_message_info, container, false)
62+
}
63+
64+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
65+
super.onViewCreated(view, savedInstanceState)
66+
setupRecyclerView()
67+
presenter.loadReadReceipts(messageId = messageId)
68+
}
69+
70+
override fun onDestroyView() {
71+
super.onDestroyView()
72+
receipt_list.removeOnScrollListener(endlessRecyclerViewScrollListener)
73+
}
74+
75+
private fun setupRecyclerView() {
76+
// Initialize the endlessRecyclerViewScrollListener so we don't NPE at onDestroyView
77+
val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, true)
78+
adapter = ReadReceiptAdapter()
79+
linearLayoutManager.stackFromEnd = true
80+
receipt_list.layoutManager = linearLayoutManager
81+
receipt_list.itemAnimator = DefaultItemAnimator()
82+
receipt_list.adapter = adapter
83+
endlessRecyclerViewScrollListener = object :
84+
EndlessRecyclerViewScrollListener(receipt_list.layoutManager as LinearLayoutManager) {
85+
override fun onLoadMore(page: Int, totalItemsCount: Int, recyclerView: RecyclerView?) {
86+
}
87+
}
88+
}
89+
90+
override fun showGenericErrorMessage() {
91+
showToast(R.string.msg_generic_error)
92+
}
93+
94+
override fun showLoading() {
95+
view_loading.setVisible(true)
96+
view_loading.show()
97+
}
98+
99+
override fun hideLoading() {
100+
view_loading.hide()
101+
view_loading.setVisible(false)
102+
}
103+
104+
override fun showReadReceipts(messageReceipts: List<ReadReceiptViewModel>) {
105+
adapter.addAll(messageReceipts)
106+
}
107+
108+
companion object {
109+
const val TAG_MESSAGE_INFO_FRAGMENT = "MessageInfoFragment"
110+
}
111+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package chat.rocket.android.chatinformation.viewmodel
2+
3+
data class ReadReceiptViewModel(
4+
val avatar: String,
5+
val name: String,
6+
val time: String
7+
)

0 commit comments

Comments
 (0)