Commit b49598d9 authored by Lucio Maciel's avatar Lucio Maciel

Improvements on the chatrooms list

parent 63e2da00
{
"formatVersion": 1,
"database": {
"version": 5,
"identityHash": "47a0c30e2696ae09bc86df16cc37279d",
"entities": [
{
"tableName": "users",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `username` TEXT, `name` TEXT, `status` TEXT NOT NULL, `utcOffset` REAL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "status",
"columnName": "status",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "utcOffset",
"columnName": "utcOffset",
"affinity": "REAL",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_users_username",
"unique": false,
"columnNames": [
"username"
],
"createSql": "CREATE INDEX `index_users_username` ON `${TABLE_NAME}` (`username`)"
}
],
"foreignKeys": []
},
{
"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, 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": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "subscriptionId",
"columnName": "subscriptionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "fullname",
"columnName": "fullname",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "ownerId",
"columnName": "ownerId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "readonly",
"columnName": "readonly",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "isDefault",
"columnName": "isDefault",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "favorite",
"columnName": "favorite",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "open",
"columnName": "open",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "alert",
"columnName": "alert",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "unread",
"columnName": "unread",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userMentions",
"columnName": "userMentions",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "groupMentions",
"columnName": "groupMentions",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "updatedAt",
"columnName": "updatedAt",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lastSeen",
"columnName": "lastSeen",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lastMessageText",
"columnName": "lastMessageText",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lastMessageUserId",
"columnName": "lastMessageUserId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lastMessageTimestamp",
"columnName": "lastMessageTimestamp",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "broadcast",
"columnName": "broadcast",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_chatrooms_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX `index_chatrooms_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_chatrooms_ownerId",
"unique": false,
"columnNames": [
"ownerId"
],
"createSql": "CREATE INDEX `index_chatrooms_ownerId` ON `${TABLE_NAME}` (`ownerId`)"
},
{
"name": "index_chatrooms_subscriptionId",
"unique": true,
"columnNames": [
"subscriptionId"
],
"createSql": "CREATE UNIQUE INDEX `index_chatrooms_subscriptionId` ON `${TABLE_NAME}` (`subscriptionId`)"
},
{
"name": "index_chatrooms_updatedAt",
"unique": false,
"columnNames": [
"updatedAt"
],
"createSql": "CREATE INDEX `index_chatrooms_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)"
},
{
"name": "index_chatrooms_lastMessageUserId",
"unique": false,
"columnNames": [
"lastMessageUserId"
],
"createSql": "CREATE INDEX `index_chatrooms_lastMessageUserId` ON `${TABLE_NAME}` (`lastMessageUserId`)"
}
],
"foreignKeys": [
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"ownerId"
],
"referencedColumns": [
"id"
]
},
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"id"
]
},
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"lastMessageUserId"
],
"referencedColumns": [
"id"
]
}
]
}
],
"setupQueries": [
"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, \"47a0c30e2696ae09bc86df16cc37279d\")"
]
}
}
\ No newline at end of file
...@@ -10,6 +10,7 @@ import chat.rocket.android.chatrooms.adapter.model.RoomUiModel ...@@ -10,6 +10,7 @@ import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import chat.rocket.android.db.model.ChatRoom import chat.rocket.android.db.model.ChatRoom
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.checkIfMyself import chat.rocket.android.infrastructure.checkIfMyself
import chat.rocket.android.server.domain.GetCurrentUserInteractor
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.showLastMessage import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
...@@ -28,6 +29,7 @@ class RoomUiModelMapper( ...@@ -28,6 +29,7 @@ class RoomUiModelMapper(
private val context: Application, private val context: Application,
private val settings: PublicSettings, private val settings: PublicSettings,
private val localRepository: LocalRepository, private val localRepository: LocalRepository,
private val userInteractor: GetCurrentUserInteractor,
private val serverUrl: String private val serverUrl: String
) { ) {
private val nameUnreadColor = ContextCompat.getColor(context, R.color.colorPrimaryText) private val nameUnreadColor = ContextCompat.getColor(context, R.color.colorPrimaryText)
...@@ -37,6 +39,10 @@ class RoomUiModelMapper( ...@@ -37,6 +39,10 @@ class RoomUiModelMapper(
private val messageUnreadColor = ContextCompat.getColor(context, android.R.color.primary_text_light) private val messageUnreadColor = ContextCompat.getColor(context, android.R.color.primary_text_light)
private val messageColor = ContextCompat.getColor(context, R.color.colorSecondaryText) private val messageColor = ContextCompat.getColor(context, R.color.colorSecondaryText)
private val currentUser by lazy {
userInteractor.get()
}
fun map(rooms: List<ChatRoom>, grouped: Boolean = false): List<ItemHolder<*>> { fun map(rooms: List<ChatRoom>, grouped: Boolean = false): List<ItemHolder<*>> {
val list = ArrayList<ItemHolder<*>>(rooms.size + 4) val list = ArrayList<ItemHolder<*>>(rooms.size + 4)
var lastType: String? = null var lastType: String? = null
...@@ -88,8 +94,9 @@ class RoomUiModelMapper( ...@@ -88,8 +94,9 @@ class RoomUiModelMapper(
name = name!!, name = name!!,
type = type, type = type,
avatar = serverUrl.avatarUrl(name!!, isGroupOrChannel = true), avatar = serverUrl.avatarUrl(name!!, isGroupOrChannel = true),
lastMessage = mapLastMessage(lastMessage?.sender?.username, lastMessage = mapLastMessage(lastMessage?.sender?.id, lastMessage?.sender?.username,
lastMessage?.sender?.name, lastMessage?.message) lastMessage?.sender?.name, lastMessage?.message,
isDirectMessage = type is RoomType.DirectMessage)
) )
} }
} }
...@@ -107,8 +114,9 @@ class RoomUiModelMapper( ...@@ -107,8 +114,9 @@ class RoomUiModelMapper(
serverUrl.avatarUrl(name, isGroupOrChannel = true) serverUrl.avatarUrl(name, isGroupOrChannel = true)
} }
val unread = mapUnread(unread) val unread = mapUnread(unread)
val lastMessage = mapLastMessage(chatRoom.lastMessageUserName, val lastMessage = mapLastMessage(lastMessageUserId, chatRoom.lastMessageUserName,
chatRoom.lastMessageUserFullName, lastMessageText, isUnread) chatRoom.lastMessageUserFullName, lastMessageText, isUnread,
type is RoomType.DirectMessage)
RoomUiModel( RoomUiModel(
id = id, id = id,
...@@ -136,14 +144,16 @@ class RoomUiModelMapper( ...@@ -136,14 +144,16 @@ class RoomUiModelMapper(
} }
} }
private fun mapLastMessage(name: String?, fullName: String?, text: String?, unread: Boolean = false): CharSequence? { private fun mapLastMessage(userId: String?, name: String?, fullName: String?, text: String?,
unread: Boolean = false,
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 (localRepository.checkIfMyself(name)) { val user = if (currentUser != null && currentUser!!.id == userId) {
"${context.getString(R.string.msg_you)}: " "${context.getString(R.string.msg_you)}: "
} else { } else {
"${mapName(name, fullName, unread)}: " if (isDirectMessage) "" else "${mapName(name, fullName, unread)}: "
} }
val color = if (unread) messageUnreadColor else messageColor val color = if (unread) messageUnreadColor else messageColor
......
...@@ -9,9 +9,12 @@ import chat.rocket.android.chatrooms.ui.ChatRoomsFragment ...@@ -9,9 +9,12 @@ import chat.rocket.android.chatrooms.ui.ChatRoomsFragment
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.UserDao
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.GetCurrentUserInteractor
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infraestructure.ConnectionManager
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
...@@ -48,6 +51,10 @@ class ChatRoomsFragmentModule { ...@@ -48,6 +51,10 @@ class ChatRoomsFragmentModule {
@PerFragment @PerFragment
fun provideChatRoomDao(manager: DatabaseManager): ChatRoomDao = manager.chatRoomDao() fun provideChatRoomDao(manager: DatabaseManager): ChatRoomDao = manager.chatRoomDao()
@Provides
@PerFragment
fun provideUserDao(manager: DatabaseManager): UserDao = manager.userDao()
@Provides @Provides
@PerFragment @PerFragment
fun provideConnectionManager( fun provideConnectionManager(
...@@ -81,8 +88,20 @@ class ChatRoomsFragmentModule { ...@@ -81,8 +88,20 @@ class ChatRoomsFragmentModule {
context: Application, context: Application,
repository: SettingsRepository, repository: SettingsRepository,
localRepository: LocalRepository, localRepository: LocalRepository,
userInteractor: GetCurrentUserInteractor,
@Named("currentServer") serverUrl: String @Named("currentServer") serverUrl: String
): RoomUiModelMapper { ): RoomUiModelMapper {
return RoomUiModelMapper(context, repository.get(serverUrl), localRepository, serverUrl) return RoomUiModelMapper(context, repository.get(serverUrl), localRepository,
userInteractor, serverUrl)
}
@Provides
@PerFragment
fun provideGetCurrentUserInteractor(
tokenRepository: TokenRepository,
@Named("currentServer") serverUrl: String,
userDao: UserDao
): GetCurrentUserInteractor {
return GetCurrentUserInteractor(tokenRepository, serverUrl, userDao)
} }
} }
\ No newline at end of file
...@@ -18,60 +18,10 @@ class FetchChatRoomsInteractor( ...@@ -18,60 +18,10 @@ class FetchChatRoomsInteractor(
suspend fun refreshChatRooms() { suspend fun refreshChatRooms() {
val rooms = retryIO("fetch chatRooms", times = 10, val rooms = retryIO("fetch chatRooms", times = 10,
initialDelay = 200, maxDelay = 2000) { initialDelay = 200, maxDelay = 2000) {
client.chatRooms().update.map { room -> client.chatRooms().update
mapChatRoom(room)
}
} }
Timber.d("Refreshing rooms: $rooms") Timber.d("Refreshing rooms: $rooms")
dbManager.insert(rooms) dbManager.processRooms(rooms)
}
private suspend fun mapChatRoom(room: ChatRoom): ChatRoomEntity {
with(room) {
val userId = userId()
if (userId != null && dbManager.findUser(userId) == null) {
Timber.d("Missing user, inserting: $userId")
dbManager.insert(UserEntity(userId))
}
lastMessage?.sender?.let { user ->
user.id?.let { id ->
if (dbManager.findUser(id) == null) {
Timber.d("Missing last message user, inserting: $id")
dbManager.insert(UserEntity(id, user.username, user.name))
}
}
}
user?.id?.let { id ->
if (dbManager.findUser(id) == null) {
Timber.d("Missing owner user, inserting: $id")
dbManager.insert(UserEntity(id, user?.username, user?.name))
}
}
return ChatRoomEntity(
id = id,
subscriptionId = subscriptionId,
type = type.toString(),
name = name,
fullname = fullName,
userId = userId,
ownerId = user?.id,
readonly = readonly,
isDefault = default,
favorite = favorite,
open = open,
alert = alert,
unread = unread,
userMentions = userMentions,
groupMentions = groupMentions,
updatedAt = updatedAt,
timestamp = timestamp,
lastSeen = lastSeen,
lastMessageText = lastMessage?.message,
lastMessageUserId = lastMessage?.sender?.id,
lastMessageTimestamp = lastMessage?.timestamp,
broadcast = broadcast
)
}
} }
} }
\ No newline at end of file
package chat.rocket.android.db package chat.rocket.android.db
import android.app.Application import android.app.Application
import androidx.room.migration.Migration
import chat.rocket.android.R
import chat.rocket.android.db.model.BaseUserEntity import chat.rocket.android.db.model.BaseUserEntity
import chat.rocket.android.db.model.ChatRoomEntity import chat.rocket.android.db.model.ChatRoomEntity
import chat.rocket.android.db.model.UserEntity import chat.rocket.android.db.model.UserEntity
...@@ -13,7 +15,12 @@ import chat.rocket.common.model.User ...@@ -13,7 +15,12 @@ import chat.rocket.common.model.User
import chat.rocket.core.internal.model.Subscription import chat.rocket.core.internal.model.Subscription
import chat.rocket.core.internal.realtime.socket.model.StreamMessage import chat.rocket.core.internal.realtime.socket.model.StreamMessage
import chat.rocket.core.internal.realtime.socket.model.Type import chat.rocket.core.internal.realtime.socket.model.Type
import chat.rocket.core.model.ChatRoom
import chat.rocket.core.model.Message
import chat.rocket.core.model.Myself
import chat.rocket.core.model.Room import chat.rocket.core.model.Room
import chat.rocket.core.model.attachment.Attachment
import chat.rocket.core.model.userId
import kotlinx.coroutines.experimental.launch import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.newSingleThreadContext import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.withContext import kotlinx.coroutines.experimental.withContext
...@@ -22,8 +29,11 @@ import java.util.HashSet ...@@ -22,8 +29,11 @@ import java.util.HashSet
class DatabaseManager(val context: Application, class DatabaseManager(val context: Application,
val serverUrl: String) { val serverUrl: String) {
private val database: RCDatabase = androidx.room.Room.databaseBuilder(context, private val database: RCDatabase = androidx.room.Room.databaseBuilder(context,
RCDatabase::class.java, serverUrl.databaseName()).fallbackToDestructiveMigration() RCDatabase::class.java, serverUrl.databaseName())
.addMigrations(RCDatabase.MIGRATION_4_5)
.fallbackToDestructiveMigration()
.build() .build()
private val dbContext = newSingleThreadContext("$serverUrl-db-context") private val dbContext = newSingleThreadContext("$serverUrl-db-context")
...@@ -91,6 +101,28 @@ class DatabaseManager(val context: Application, ...@@ -91,6 +101,28 @@ class DatabaseManager(val context: Application,
} }
} }
fun updateSelfUser(myself: Myself) {
launch(dbContext) {
val user = userDao().getUser(myself.id)
val entity = user?.copy(
name = myself.name ?: user.name,
username = myself.username ?: user.username,
utcOffset = myself.utcOffset ?: user.utcOffset,
status = myself.status?.toString() ?: user.status
) ?: myself.asUser().toEntity()
Timber.d("UPDATING SELF: $entity")
entity?.let { userDao().upsert(entity) }
}
}
fun processRooms(rooms: List<ChatRoom>) {
launch(dbContext) {
val entities = rooms.map { mapChatRoom(it) }
chatRoomDao().insertOrReplace(entities)
}
}
private suspend fun createUpdates(): List<ChatRoomEntity> { private suspend fun createUpdates(): List<ChatRoomEntity> {
val list = ArrayList<ChatRoomEntity>() val list = ArrayList<ChatRoomEntity>()
...@@ -140,30 +172,24 @@ class DatabaseManager(val context: Application, ...@@ -140,30 +172,24 @@ class DatabaseManager(val context: Application,
} }
} }
private suspend fun updateChatRoom(data: BaseRoom): ChatRoomEntity? {
return when(data) {
is Room -> updateRoom(data)
is Subscription -> updateSubscription(data)
else -> null
}
}
private suspend fun updateRoom(data: Room): ChatRoomEntity? { private suspend fun updateRoom(data: Room): ChatRoomEntity? {
return chatRoomDao().get(data.id)?.let { current -> return chatRoomDao().get(data.id)?.let { current ->
with(data) { with(data) {
val chatRoom = current.chatRoom val chatRoom = current.chatRoom
lastMessage?.sender?.let { user -> lastMessage?.sender?.let { user ->
if (findUser(user.id) == null) { user.id?.let { id ->
Timber.d("Missing last message user, inserting: ${user.id}") if (findUser(id) == null) {
insert(UserEntity(user.id!!, user.username, user.name)) Timber.d("Missing last message user, inserting: $id")
insert(UserEntity(id, user.username, user.name))
}
} }
} }
user?.let { user -> user?.id?.let { id ->
if (findUser(user.id) == null) { if (findUser(id) == null) {
Timber.d("Missing owner user, inserting: ${user.id}") Timber.d("Missing owner user, inserting: $id")
insert(UserEntity(user.id!!, user.username, user.name)) insert(UserEntity(id, user!!.username, user!!.name))
} }
} }
...@@ -173,7 +199,7 @@ class DatabaseManager(val context: Application, ...@@ -173,7 +199,7 @@ class DatabaseManager(val context: Application,
ownerId = user?.id ?: chatRoom.ownerId, ownerId = user?.id ?: chatRoom.ownerId,
readonly = readonly, readonly = readonly,
updatedAt = updatedAt ?: chatRoom.updatedAt, updatedAt = updatedAt ?: chatRoom.updatedAt,
lastMessageText = lastMessage?.message, lastMessageText = mapLastMessageText(lastMessage),
lastMessageUserId = lastMessage?.sender?.id, lastMessageUserId = lastMessage?.sender?.id,
lastMessageTimestamp = lastMessage?.timestamp lastMessageTimestamp = lastMessage?.timestamp
) )
...@@ -181,6 +207,21 @@ class DatabaseManager(val context: Application, ...@@ -181,6 +207,21 @@ class DatabaseManager(val context: Application,
} }
} }
private fun mapLastMessageText(message: Message?): String? {
return if (message == null) {
null
} else {
return if (message.message.isEmpty() && message.attachments?.isNotEmpty() == true) {
mapAttachmentText(message.attachments!![0])
} else {
message.message
}
}
}
private fun mapAttachmentText(attachment: Attachment): String =
context.getString(R.string.msg_sent_attachment)
private suspend fun updateSubscription(data: Subscription): ChatRoomEntity? { private suspend fun updateSubscription(data: Subscription): ChatRoomEntity? {
return chatRoomDao().get(data.roomId)?.let { current -> return chatRoomDao().get(data.roomId)?.let { current ->
with(data) { with(data) {
...@@ -262,16 +303,20 @@ class DatabaseManager(val context: Application, ...@@ -262,16 +303,20 @@ class DatabaseManager(val context: Application,
} }
room.lastMessage?.sender?.let { user -> room.lastMessage?.sender?.let { user ->
if (findUser(user.id) == null) { user.id?.let { id ->
Timber.d("Missing last message user, inserting: ${user.id}") if (findUser(id) == null) {
insert(UserEntity(user.id!!, user.username, user.name)) Timber.d("Missing last message user, inserting: $id")
insert(UserEntity(id, user.username, user.name))
}
} }
} }
room.user?.let { user -> room.user?.let { user ->
if (findUser(user.id) == null) { user.id?.let { id ->
Timber.d("Missing owner user, inserting: ${user.id}") if (findUser(id) == null) {
insert(UserEntity(user.id!!, user.username, user.name)) Timber.d("Missing owner user, inserting: $id")
insert(UserEntity(id, user.username, user.name))
}
} }
} }
...@@ -294,13 +339,64 @@ class DatabaseManager(val context: Application, ...@@ -294,13 +339,64 @@ class DatabaseManager(val context: Application,
updatedAt = subscription.updatedAt, updatedAt = subscription.updatedAt,
timestamp = subscription.timestamp, timestamp = subscription.timestamp,
lastSeen = subscription.lastSeen, lastSeen = subscription.lastSeen,
lastMessageText = room.lastMessage?.message, lastMessageText = mapLastMessageText(room.lastMessage),
lastMessageUserId = room.lastMessage?.sender?.id, lastMessageUserId = room.lastMessage?.sender?.id,
lastMessageTimestamp = room.lastMessage?.timestamp, lastMessageTimestamp = room.lastMessage?.timestamp,
broadcast = room.broadcast broadcast = room.broadcast
) )
} }
private suspend fun mapChatRoom(room: ChatRoom): ChatRoomEntity {
with(room) {
val userId = userId()
if (userId != null && findUser(userId) == null) {
Timber.d("Missing user, inserting: $userId")
insert(UserEntity(userId))
}
lastMessage?.sender?.let { user ->
user.id?.let { id ->
if (findUser(id) == null) {
Timber.d("Missing last message user, inserting: $id")
insert(UserEntity(id, user.username, user.name))
}
}
}
user?.id?.let { id ->
if (findUser(id) == null) {
Timber.d("Missing owner user, inserting: $id")
insert(UserEntity(id, user?.username, user?.name))
}
}
return ChatRoomEntity(
id = id,
subscriptionId = subscriptionId,
type = type.toString(),
name = name,
fullname = fullName,
userId = userId,
ownerId = user?.id,
readonly = readonly,
isDefault = default,
favorite = favorite,
open = open,
alert = alert,
unread = unread,
userMentions = userMentions,
groupMentions = groupMentions,
updatedAt = updatedAt,
timestamp = timestamp,
lastSeen = lastSeen,
lastMessageText = mapLastMessageText(lastMessage),
lastMessageUserId = lastMessage?.sender?.id,
lastMessageTimestamp = lastMessage?.timestamp,
broadcast = broadcast
)
}
}
suspend fun insert(rooms: List<ChatRoomEntity>) { suspend fun insert(rooms: List<ChatRoomEntity>) {
withContext(dbContext) { withContext(dbContext) {
chatRoomDao().cleanInsert(rooms) chatRoomDao().cleanInsert(rooms)
...@@ -313,7 +409,7 @@ class DatabaseManager(val context: Application, ...@@ -313,7 +409,7 @@ class DatabaseManager(val context: Application,
} }
} }
fun findUser(userId: String?): String? = if (userId != null) userDao().findUser(userId) else null fun findUser(userId: String): String? = userDao().findUser(userId)
} }
fun User.toEntity(): BaseUserEntity? { fun User.toEntity(): BaseUserEntity? {
...@@ -326,6 +422,10 @@ fun User.toEntity(): BaseUserEntity? { ...@@ -326,6 +422,10 @@ fun User.toEntity(): BaseUserEntity? {
} }
} }
private fun Myself.asUser(): User {
return User(id, name, username, status, utcOffset, null, roles)
}
private fun String.databaseName(): String { private fun String.databaseName(): String {
val tmp = this.removePrefix("https://") val tmp = this.removePrefix("https://")
.removePrefix("http://") .removePrefix("http://")
......
...@@ -2,16 +2,29 @@ package chat.rocket.android.db ...@@ -2,16 +2,29 @@ package chat.rocket.android.db
import androidx.room.Database import androidx.room.Database
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import chat.rocket.android.db.model.ChatRoomEntity import chat.rocket.android.db.model.ChatRoomEntity
import chat.rocket.android.db.model.UserEntity import chat.rocket.android.db.model.UserEntity
@Database( @Database(
entities = [UserEntity::class, ChatRoomEntity::class], entities = [UserEntity::class, ChatRoomEntity::class],
version = 4, version = 5,
exportSchema = true exportSchema = true
) )
abstract class RCDatabase : RoomDatabase() { abstract class RCDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun chatRoomDao(): ChatRoomDao abstract fun chatRoomDao(): ChatRoomDao
companion object {
@JvmField
val MIGRATION_4_5 = Migration4to5()
}
}
class Migration4to5 : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE INDEX `index_chatrooms_lastMessageUserId` ON `chatrooms` (`lastMessageUserId`)")
}
} }
\ No newline at end of file
...@@ -22,6 +22,9 @@ abstract class UserDao : BaseDao<UserEntity> { ...@@ -22,6 +22,9 @@ abstract class UserDao : BaseDao<UserEntity> {
@Query("SELECT id FROM users WHERE ID = :id") @Query("SELECT id FROM users WHERE ID = :id")
abstract fun findUser(id: String): String? abstract fun findUser(id: String): String?
@Query("SELECT * FROM users WHERE ID = :id")
abstract fun getUser(id:String): UserEntity?
@Transaction @Transaction
open fun upsert(user: BaseUserEntity) { open fun upsert(user: BaseUserEntity) {
internalUpsert(user) internalUpsert(user)
......
...@@ -11,7 +11,8 @@ import androidx.room.PrimaryKey ...@@ -11,7 +11,8 @@ import androidx.room.PrimaryKey
Index(value = ["userId"]), Index(value = ["userId"]),
Index(value = ["ownerId"]), Index(value = ["ownerId"]),
Index(value = ["subscriptionId"], unique = true), Index(value = ["subscriptionId"], unique = true),
Index(value = ["updatedAt"]) Index(value = ["updatedAt"]),
Index(value = ["lastMessageUserId"])
], ],
foreignKeys = [ foreignKeys = [
ForeignKey(entity = UserEntity::class, parentColumns = ["id"], childColumns = ["ownerId"]), ForeignKey(entity = UserEntity::class, parentColumns = ["id"], childColumns = ["ownerId"]),
...@@ -19,7 +20,6 @@ import androidx.room.PrimaryKey ...@@ -19,7 +20,6 @@ import androidx.room.PrimaryKey
ForeignKey(entity = UserEntity::class, parentColumns = ["id"], childColumns = ["lastMessageUserId"]) ForeignKey(entity = UserEntity::class, parentColumns = ["id"], childColumns = ["lastMessageUserId"])
] ]
) )
data class ChatRoomEntity( data class ChatRoomEntity(
@PrimaryKey var id: String, @PrimaryKey var id: String,
var subscriptionId: String, var subscriptionId: String,
......
...@@ -32,5 +32,6 @@ interface LocalRepository { ...@@ -32,5 +32,6 @@ interface LocalRepository {
} }
} }
// FIXME - we are saving the user full name here when the server is UI_Use_Real_Name true
fun LocalRepository.checkIfMyself(username: String) = username() == username fun LocalRepository.checkIfMyself(username: String) = username() == username
fun LocalRepository.username() = get(LocalRepository.CURRENT_USERNAME_KEY) fun LocalRepository.username() = get(LocalRepository.CURRENT_USERNAME_KEY)
\ No newline at end of file
...@@ -9,6 +9,7 @@ import chat.rocket.android.server.domain.GetAccountsInteractor ...@@ -9,6 +9,7 @@ import chat.rocket.android.server.domain.GetAccountsInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.domain.RemoveAccountInteractor import chat.rocket.android.server.domain.RemoveAccountInteractor
import chat.rocket.android.server.domain.SaveAccountInteractor import chat.rocket.android.server.domain.SaveAccountInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
...@@ -33,6 +34,7 @@ import chat.rocket.core.internal.rest.unregisterPushToken ...@@ -33,6 +34,7 @@ import chat.rocket.core.internal.rest.unregisterPushToken
import chat.rocket.core.model.Myself import chat.rocket.core.model.Myself
import kotlinx.coroutines.experimental.CommonPool import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.channels.Channel import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext import kotlinx.coroutines.experimental.withContext
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
...@@ -43,6 +45,7 @@ class MainPresenter @Inject constructor( ...@@ -43,6 +45,7 @@ class MainPresenter @Inject constructor(
private val navigator: MainNavigator, private val navigator: MainNavigator,
private val tokenRepository: TokenRepository, private val tokenRepository: TokenRepository,
private val serverInteractor: GetCurrentServerInteractor, private val serverInteractor: GetCurrentServerInteractor,
private val refreshSettingsInteractor: RefreshSettingsInteractor,
private val localRepository: LocalRepository, private val localRepository: LocalRepository,
private val navHeaderMapper: NavHeaderUiModelMapper, private val navHeaderMapper: NavHeaderUiModelMapper,
private val saveAccountInteractor: SaveAccountInteractor, private val saveAccountInteractor: SaveAccountInteractor,
...@@ -149,6 +152,7 @@ class MainPresenter @Inject constructor( ...@@ -149,6 +152,7 @@ class MainPresenter @Inject constructor(
} }
fun connect() { fun connect() {
launch { refreshSettingsInteractor.refresh(currentServer) }
manager.connect() manager.connect()
} }
......
package chat.rocket.android.server.domain
import chat.rocket.android.db.UserDao
import chat.rocket.android.db.model.UserEntity
class GetCurrentUserInteractor(
private val tokenRepository: TokenRepository,
private val currentServer: String,
private val userDao: UserDao
) {
fun get(): UserEntity? {
return tokenRepository.get(currentServer)?.let {
userDao.getUser(it.userId)
}
}
}
...@@ -149,7 +149,7 @@ class ConnectionManager( ...@@ -149,7 +149,7 @@ class ConnectionManager(
launch(parent = connectJob) { launch(parent = connectJob) {
for (myself in client.userDataChannel) { for (myself in client.userDataChannel) {
Timber.d("Got userData") Timber.d("Got userData")
userActor.send(myself.asUser()) dbManager.updateSelfUser(myself)
for (channel in userDataChannels) { for (channel in userDataChannels) {
channel.send(myself) channel.send(myself)
} }
...@@ -260,10 +260,6 @@ class ConnectionManager( ...@@ -260,10 +260,6 @@ class ConnectionManager(
} }
} }
private fun Myself.asUser(): User {
return User(id, name, username, status, utcOffset, null, roles)
}
private fun Long.orZero(): Long { private fun Long.orZero(): Long {
return if (this < 0) 0 else this return if (this < 0) 0 else this
} }
......
...@@ -292,4 +292,5 @@ ...@@ -292,4 +292,5 @@
<string name="read_by">Leído por</string> <string name="read_by">Leído por</string>
<string name="message_information_title">Información del mensaje</string> <string name="message_information_title">Información del mensaje</string>
<string name="msg_log_out">Saliendo de tu cuenta…</string> <string name="msg_log_out">Saliendo de tu cuenta…</string>
<string name="msg_sent_attachment">Envió un archivo</string>
</resources> </resources>
...@@ -293,4 +293,5 @@ ...@@ -293,4 +293,5 @@
<string name="read_by">Lire par</string> <string name="read_by">Lire par</string>
<string name="message_information_title">Informations sur le message</string> <string name="message_information_title">Informations sur le message</string>
<string name="msg_log_out">Déconnecter…</string> <string name="msg_log_out">Déconnecter…</string>
<string name="msg_sent_attachment">Envoyé un fichier</string>
</resources> </resources>
...@@ -272,4 +272,5 @@ ...@@ -272,4 +272,5 @@
<string name="read_by">Lida por</string> <string name="read_by">Lida por</string>
<string name="message_information_title">Informações da mensagem</string> <string name="message_information_title">Informações da mensagem</string>
<string name="msg_log_out">Deslogando…</string> <string name="msg_log_out">Deslogando…</string>
<string name="msg_sent_attachment">Enviou um arquivo</string>
</resources> </resources>
...@@ -124,6 +124,7 @@ ...@@ -124,6 +124,7 @@
<string name="msg_upload_file">Upload file</string> <string name="msg_upload_file">Upload file</string>
<string name="msg_file_description">File description</string> <string name="msg_file_description">File description</string>
<string name="msg_send">Send</string> <string name="msg_send">Send</string>
<string name="msg_sent_attachment">Sent an attachment</string>
<!-- Create channel messages --> <!-- Create channel messages -->
<string name="msg_private_channel">Private</string> <string name="msg_private_channel">Private</string>
......
...@@ -24,9 +24,9 @@ ext { ...@@ -24,9 +24,9 @@ ext {
playServices : '15.0.0', playServices : '15.0.0',
exoPlayer : '2.6.0', exoPlayer : '2.6.0',
flexbox : '0.3.2', flexbox : '0.3.2',
material : '1.0.0-alpha1', material : '1.0.0-beta01',
room : '2.0.0-alpha1', room : '2.0.0-beta01',
lifecycle : '2.0.0-beta01', lifecycle : '2.0.0-beta01',
rxKotlin : '2.2.0', rxKotlin : '2.2.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