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

Commit e6a051d

Browse files
authored
Merge branch 'develop' into language-change-fix
2 parents 2db4cf8 + 0c21f1d commit e6a051d

19 files changed

Lines changed: 427 additions & 255 deletions

File tree

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ android {
1818
applicationId "chat.rocket.android"
1919
minSdkVersion versions.minSdk
2020
targetSdkVersion versions.targetSdk
21-
versionCode 2065
21+
versionCode 2067
2222
versionName "3.4.0"
2323
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
2424
multiDexEnabled true
@@ -204,4 +204,4 @@ task compileSdk(type: Exec) {
204204
preBuild.dependsOn compileSdk
205205
if (isPlay) {
206206
apply plugin: 'com.google.gms.google-services'
207-
}
207+
}

app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt

Lines changed: 156 additions & 106 deletions
Large diffs are not rendered by default.

app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@ import androidx.core.view.isVisible
2929
import androidx.fragment.app.Fragment
3030
import androidx.fragment.app.FragmentManager
3131
import androidx.recyclerview.widget.DefaultItemAnimator
32+
import androidx.recyclerview.widget.ItemTouchHelper
3233
import androidx.recyclerview.widget.LinearLayoutManager
3334
import androidx.recyclerview.widget.RecyclerView
3435
import chat.rocket.android.R
3536
import chat.rocket.android.analytics.AnalyticsManager
3637
import chat.rocket.android.analytics.event.ScreenViewEvent
38+
import chat.rocket.android.chatroom.adapter.AttachmentViewHolder
3739
import chat.rocket.android.chatroom.adapter.ChatRoomAdapter
3840
import chat.rocket.android.chatroom.adapter.CommandSuggestionsAdapter
3941
import chat.rocket.android.chatroom.adapter.EmojiSuggestionsAdapter
42+
import chat.rocket.android.chatroom.adapter.MessageViewHolder
4043
import chat.rocket.android.chatroom.adapter.PEOPLE
4144
import chat.rocket.android.chatroom.adapter.PeopleSuggestionsAdapter
4245
import chat.rocket.android.chatroom.adapter.RoomSuggestionsAdapter
@@ -156,7 +159,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
156159
lateinit var analyticsManager: AnalyticsManager
157160
@Inject
158161
lateinit var navigator: ChatRoomNavigator
159-
private lateinit var adapter: ChatRoomAdapter
162+
private lateinit var chatRoomAdapter: ChatRoomAdapter
160163
internal lateinit var chatRoomId: String
161164
private lateinit var chatRoomName: String
162165
internal lateinit var chatRoomType: String
@@ -289,7 +292,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
289292
}
290293
?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
291294

292-
adapter = ChatRoomAdapter(
295+
chatRoomAdapter = ChatRoomAdapter(
293296
roomId = chatRoomId,
294297
roomType = chatRoomType,
295298
roomName = chatRoomName,
@@ -388,7 +391,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
388391
override fun showMessages(dataSet: List<BaseUiModel<*>>, clearDataSet: Boolean) {
389392
ui {
390393
if (clearDataSet) {
391-
adapter.clearData()
394+
chatRoomAdapter.clearData()
392395
}
393396

394397
if (dataSet.isNotEmpty()) {
@@ -429,35 +432,22 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
429432
}
430433
}
431434

432-
if (recycler_view.adapter == null) {
433-
recycler_view.adapter = adapter
434-
if (dataSet.size >= 30) {
435-
recycler_view.addOnScrollListener(endlessRecyclerViewScrollListener)
436-
}
437-
recycler_view.addOnLayoutChangeListener(layoutChangeListener)
438-
recycler_view.addOnScrollListener(onScrollListener)
439-
440-
// Load just once, on the first page...
441-
presenter.loadActiveMembers(chatRoomId, chatRoomType, filterSelfOut = true)
442-
}
443-
444-
val oldMessagesCount = adapter.itemCount
445-
adapter.appendData(dataSet)
435+
val oldMessagesCount = chatRoomAdapter.itemCount
436+
chatRoomAdapter.appendData(dataSet)
446437
if (oldMessagesCount == 0 && dataSet.isNotEmpty()) {
447438
recycler_view.scrollToPosition(0)
448439
verticalScrollOffset.set(0)
449440
}
450-
presenter.loadActiveMembers(chatRoomId, chatRoomType, filterSelfOut = true)
451-
empty_chat_view.isVisible = adapter.itemCount == 0
441+
empty_chat_view.isVisible = chatRoomAdapter.itemCount == 0
452442
dismissEmojiKeyboard()
453443
}
454444
}
455445

456446
override fun showSearchedMessages(dataSet: List<BaseUiModel<*>>) {
457447
recycler_view.removeOnScrollListener(endlessRecyclerViewScrollListener)
458-
adapter.clearData()
459-
adapter.prependData(dataSet)
460-
empty_chat_view.isVisible = adapter.itemCount == 0
448+
chatRoomAdapter.clearData()
449+
chatRoomAdapter.prependData(dataSet)
450+
empty_chat_view.isVisible = chatRoomAdapter.itemCount == 0
461451
dismissEmojiKeyboard()
462452
}
463453

@@ -469,10 +459,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
469459
setupMessageComposer(roomUiModel)
470460
isBroadcastChannel = roomUiModel.broadcast
471461
isFavorite = roomUiModel.favorite.orFalse()
472-
if (isBroadcastChannel && !roomUiModel.canModerate) {
473-
disableMenu = true
474-
activity?.invalidateOptionsMenu()
475-
}
462+
disableMenu = (roomUiModel.broadcast && !roomUiModel.canModerate)
463+
activity?.invalidateOptionsMenu()
476464
}
477465
}
478466

@@ -542,7 +530,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
542530

543531
override fun showNewMessage(message: List<BaseUiModel<*>>, isMessageReceived: Boolean) {
544532
ui {
545-
adapter.prependData(message)
533+
chatRoomAdapter.prependData(message)
546534
if (isMessageReceived && button_fab.isVisible) {
547535
newMessageCount++
548536
if (newMessageCount <= 99) {
@@ -555,7 +543,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
555543
recycler_view.scrollToPosition(0)
556544
}
557545
verticalScrollOffset.set(0)
558-
empty_chat_view.isVisible = adapter.itemCount == 0
546+
empty_chat_view.isVisible = chatRoomAdapter.itemCount == 0
559547
dismissEmojiKeyboard()
560548
}
561549
}
@@ -565,9 +553,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
565553
// TODO - investigate WHY we get a empty list here
566554
if (message.isEmpty()) return@ui
567555

568-
if (adapter.updateItem(message.last())) {
556+
if (chatRoomAdapter.updateItem(message.last())) {
569557
if (message.size > 1) {
570-
adapter.prependData(listOf(message.first()))
558+
chatRoomAdapter.prependData(listOf(message.first()))
571559
}
572560
} else {
573561
showNewMessage(message, true)
@@ -578,7 +566,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
578566

579567
override fun dispatchDeleteMessage(msgId: String) {
580568
ui {
581-
adapter.removeItem(msgId)
569+
chatRoomAdapter.removeItem(msgId)
582570
}
583571
}
584572

@@ -807,7 +795,56 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
807795
presenter.loadMessages(chatRoomId, chatRoomType, page * 30L)
808796
}
809797
}
810-
recycler_view.addOnScrollListener(fabScrollListener)
798+
799+
with (recycler_view) {
800+
adapter = chatRoomAdapter
801+
addOnScrollListener(endlessRecyclerViewScrollListener)
802+
addOnLayoutChangeListener(layoutChangeListener)
803+
addOnScrollListener(onScrollListener)
804+
addOnScrollListener(fabScrollListener)
805+
}
806+
if (!isReadOnly) {
807+
val touchCallback: ItemTouchHelper.SimpleCallback =
808+
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
809+
override fun onMove(
810+
recyclerView: RecyclerView,
811+
viewHolder: RecyclerView.ViewHolder,
812+
target: RecyclerView.ViewHolder
813+
): Boolean {
814+
return true
815+
}
816+
817+
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
818+
var replyId: String? = null
819+
820+
when (viewHolder) {
821+
is MessageViewHolder -> replyId = viewHolder.data?.messageId
822+
is AttachmentViewHolder -> replyId = viewHolder.data?.messageId
823+
}
824+
825+
replyId?.let {
826+
citeMessage(chatRoomName, chatRoomType, it, true)
827+
}
828+
829+
chatRoomAdapter.notifyItemChanged(viewHolder.adapterPosition)
830+
}
831+
832+
override fun getSwipeDirs(
833+
recyclerView: RecyclerView,
834+
viewHolder: RecyclerView.ViewHolder
835+
): Int {
836+
// Currently enable swipes for text and attachment messages only
837+
838+
if (viewHolder is MessageViewHolder || viewHolder is AttachmentViewHolder) {
839+
return super.getSwipeDirs(recyclerView, viewHolder)
840+
}
841+
842+
return 0
843+
}
844+
}
845+
846+
ItemTouchHelper(touchCallback).attachToRecyclerView(recycler_view)
847+
}
811848
}
812849

813850
private fun setupFab() {

app/src/main/java/chat/rocket/android/db/DatabaseManager.kt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package chat.rocket.android.db
22

33
import android.app.Application
4+
import androidx.core.net.toUri
45
import chat.rocket.android.R
56
import chat.rocket.android.db.model.BaseMessageEntity
67
import chat.rocket.android.db.model.BaseUserEntity
@@ -15,6 +16,7 @@ import chat.rocket.android.db.model.UrlEntity
1516
import chat.rocket.android.db.model.UserEntity
1617
import chat.rocket.android.db.model.UserStatus
1718
import chat.rocket.android.db.model.asEntity
19+
import chat.rocket.android.util.extensions.avatarUrl
1820
import chat.rocket.android.util.extensions.exhaustive
1921
import chat.rocket.android.util.extensions.removeTrailingSlash
2022
import chat.rocket.android.util.extensions.toEntity
@@ -23,6 +25,7 @@ import chat.rocket.android.util.retryDB
2325
import chat.rocket.common.model.BaseRoom
2426
import chat.rocket.common.model.RoomType
2527
import chat.rocket.common.model.SimpleUser
28+
import chat.rocket.common.model.Token
2629
import chat.rocket.common.model.User
2730
import chat.rocket.core.internal.model.Subscription
2831
import chat.rocket.core.internal.realtime.socket.model.StreamMessage
@@ -32,6 +35,7 @@ import chat.rocket.core.model.Message
3235
import chat.rocket.core.model.Myself
3336
import chat.rocket.core.model.Room
3437
import chat.rocket.core.model.userId
38+
import com.facebook.drawee.backends.pipeline.Fresco
3539
import kotlinx.coroutines.GlobalScope
3640
import kotlinx.coroutines.Job
3741
import kotlinx.coroutines.channels.Channel
@@ -48,8 +52,7 @@ import kotlin.collections.component2
4852
import kotlin.collections.set
4953
import kotlin.system.measureTimeMillis
5054

51-
class DatabaseManager(val context: Application, val serverUrl: String) {
52-
55+
class DatabaseManager(val context: Application, val serverUrl: String, val token: Token) {
5356
private val database: RCDatabase = androidx.room.Room.databaseBuilder(
5457
context,
5558
RCDatabase::class.java, serverUrl.databaseName()
@@ -58,23 +61,23 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
5861
.build()
5962
private val dbContext = newSingleThreadContext("$serverUrl-db-context")
6063
private val dbManagerContext = newSingleThreadContext("$serverUrl-db-manager-context")
61-
6264
private val writeChannel = Channel<Operation>(Channel.UNLIMITED)
6365
private var dbJob: Job? = null
64-
6566
private val insertSubs = HashMap<String, Subscription>()
6667
private val insertRooms = HashMap<String, Room>()
6768
private val updateSubs = LinkedHashMap<String, Subscription>()
6869
private val updateRooms = LinkedHashMap<String, Room>()
6970

70-
fun chatRoomDao(): ChatRoomDao = database.chatRoomDao()
71-
fun userDao(): UserDao = database.userDao()
72-
fun messageDao(): MessageDao = database.messageDao()
73-
7471
init {
7572
start()
7673
}
7774

75+
fun chatRoomDao(): ChatRoomDao = database.chatRoomDao()
76+
77+
fun userDao(): UserDao = database.userDao()
78+
79+
fun messageDao(): MessageDao = database.messageDao()
80+
7881
fun start() {
7982
dbJob?.cancel()
8083
dbJob = GlobalScope.launch(dbContext) {
@@ -189,6 +192,20 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
189192
status = myself.status?.toString() ?: user.status
190193
) ?: myself.asUser().toEntity()
191194

195+
if (myself.avatarOrigin != null && myself.active == null &&
196+
myself.name == null && myself.username == null
197+
) {
198+
user?.username?.let {
199+
Fresco.getImagePipeline().evictFromCache(
200+
serverUrl.avatarUrl(
201+
it,
202+
token.userId,
203+
token.authToken
204+
).toUri()
205+
)
206+
}
207+
}
208+
192209
Timber.d("UPDATING SELF: $entity")
193210
entity?.let { sendOperation(Operation.UpsertUser(it)) }
194211
}
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package chat.rocket.android.db
22

33
import android.app.Application
4+
import chat.rocket.android.server.domain.TokenRepository
45
import timber.log.Timber
56
import javax.inject.Inject
67
import javax.inject.Singleton
78

89
@Singleton
9-
class DatabaseManagerFactory @Inject constructor(private val context: Application) {
10+
class DatabaseManagerFactory @Inject constructor(
11+
private val context: Application,
12+
private val tokenRepository: TokenRepository
13+
) {
1014
private val cache = HashMap<String, DatabaseManager>()
1115

1216
fun create(serverUrl: String): DatabaseManager {
@@ -15,9 +19,10 @@ class DatabaseManagerFactory @Inject constructor(private val context: Applicatio
1519
return it
1620
}
1721

18-
Timber.d("Returning FRESH database for $serverUrl")
19-
val db = DatabaseManager(context, serverUrl)
20-
cache[serverUrl] = db
21-
return db
22+
Timber.d("Returning fresh database for $serverUrl")
23+
with(DatabaseManager(context, serverUrl, tokenRepository.get(serverUrl)!!)) {
24+
cache[serverUrl] = this
25+
return this
26+
}
2227
}
2328
}

app/src/main/java/chat/rocket/android/userdetails/presentation/UserDetailsPresenter.kt

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,21 @@ class UserDetailsPresenter @Inject constructor(
4747
view.showLoading()
4848
dbManager.getUser(userId)?.let {
4949
userEntity = it
50-
val avatarUrl =
51-
userEntity.username?.let { username ->
52-
currentServer.avatarUrl(
53-
username,
54-
token?.userId,
55-
token?.authToken
56-
)
57-
}
50+
val avatarUrl = userEntity.username?.let { username ->
51+
currentServer.avatarUrl(username, token?.userId, token?.authToken)
52+
}
5853
val username = userEntity.username
5954
val name = userEntity.name
60-
val utcOffset =
61-
userEntity.utcOffset // TODO Convert UTC and display like the mockup
55+
val utcOffset = userEntity.utcOffset // FIXME Convert UTC
6256

63-
if (avatarUrl != null && username != null && name != null && utcOffset != null) {
64-
view.showUserDetailsAndActions(
65-
avatarUrl = avatarUrl,
66-
name = name,
67-
username = username,
68-
status = userEntity.status,
69-
utcOffset = utcOffset.toString(),
70-
isVideoCallAllowed = settings.isJitsiEnabled()
71-
)
72-
} else {
73-
throw Exception()
74-
}
57+
view.showUserDetailsAndActions(
58+
avatarUrl = avatarUrl,
59+
name = name,
60+
username = username,
61+
status = userEntity.status,
62+
utcOffset = utcOffset.toString(),
63+
isVideoCallAllowed = settings.isJitsiEnabled()
64+
)
7565
}
7666
} catch (ex: Exception) {
7767
Timber.e(ex)

0 commit comments

Comments
 (0)