Commit 2e903a9d authored by Lucio Maciel's avatar Lucio Maciel

Add ownerId and fullname to Room table, onclick support

parent 35285092
......@@ -12,6 +12,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class LoginFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun loginView(frag: LoginFragment): LoginView {
......
......@@ -12,6 +12,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class RegisterUsernameFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun registerUsernameView(frag: RegisterUsernameFragment): RegisterUsernameView {
......
......@@ -12,6 +12,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class ResetPasswordFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun resetPasswordView(frag: ResetPasswordFragment): ResetPasswordView {
......
......@@ -4,6 +4,7 @@ import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.authentication.server.presentation.ServerView
import chat.rocket.android.authentication.server.ui.ServerFragment
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
......@@ -12,16 +13,23 @@ import kotlinx.coroutines.experimental.Job
class ServerFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun serverView(frag: ServerFragment): ServerView {
return frag
}
@Provides
@PerFragment
fun provideLifecycleOwner(frag: ServerFragment): LifecycleOwner {
return frag
}
@Provides
@PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
......
package chat.rocket.android.authentication.server.di
import chat.rocket.android.authentication.server.ui.ServerFragment
import chat.rocket.android.dagger.scope.PerFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
......@@ -8,5 +9,6 @@ import dagger.android.ContributesAndroidInjector
abstract class ServerFragmentProvider {
@ContributesAndroidInjector(modules = [ServerFragmentModule::class])
@PerFragment
abstract fun provideServerFragment(): ServerFragment
}
\ No newline at end of file
......@@ -12,6 +12,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class SignupFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun signupView(frag: SignupFragment): SignupView {
......
......@@ -12,6 +12,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class TwoFAFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun loginView(frag: TwoFAFragment): TwoFAView {
......
......@@ -14,6 +14,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class ChatRoomFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun chatRoomView(frag: ChatRoomFragment): ChatRoomView {
......
......@@ -11,7 +11,7 @@ import chat.rocket.common.model.UserStatus
import kotlinx.android.synthetic.main.item_chat.view.*
import kotlinx.android.synthetic.main.unread_messages_badge.view.*
class RoomViewHolder(itemView: View) : ViewHolder<RoomItemHolder>(itemView) {
class RoomViewHolder(itemView: View, private val listener: (String) -> Unit) : ViewHolder<RoomItemHolder>(itemView) {
private val resources: Resources = itemView.resources
private val channelUnread: Drawable = resources.getDrawable(R.drawable.ic_hashtag_unread_12dp)
......@@ -55,6 +55,10 @@ class RoomViewHolder(itemView: View) : ViewHolder<RoomItemHolder>(itemView) {
} else {
image_chat_icon.setImageDrawable(getRoomDrawable(room.type, room.alert))
}
setOnClickListener {
listener(room.id)
}
}
}
......
......@@ -5,7 +5,7 @@ import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.util.extensions.inflate
class RoomsAdapter : RecyclerView.Adapter<ViewHolder<*>>() {
class RoomsAdapter(private val listener: (String) -> Unit) : RecyclerView.Adapter<ViewHolder<*>>() {
init {
setHasStableIds(true)
......@@ -20,7 +20,7 @@ class RoomsAdapter : RecyclerView.Adapter<ViewHolder<*>>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<*> {
if (viewType == 0) {
val view = parent.inflate(R.layout.item_chat)
return RoomViewHolder(view)
return RoomViewHolder(view, listener)
} else if (viewType == 1) {
val view = parent.inflate(R.layout.item_chatroom_header)
return HeaderViewHolder(view)
......
......@@ -48,12 +48,20 @@ class FetchChatRoomsInteractor(
dbManager.insert(UserEntity(user.id!!, user.username, user.name))
}
}
user?.let { user ->
if (dbManager.findUser(user.id!!) == null) {
Timber.d("Missing owner user, inserting: ${user.id}")
dbManager.insert(UserEntity(user.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,
......
......@@ -111,26 +111,26 @@ class ChatRoomsPresenter @Inject constructor(
}
}
fun loadChatRoom(chatRoom: ChatRoom) {
val isDirectMessage = chatRoom.type is RoomType.DirectMessage
val roomName = if (isDirectMessage
&& chatRoom.fullName != null
&& settings.useRealName()) {
chatRoom.fullName!!
} else {
chatRoom.name
}
launchUI(strategy) {
val myself = getCurrentUser()
if (myself?.username == null) {
view.showMessage(R.string.msg_generic_error)
fun loadChatRoom(chatRoom: chat.rocket.android.db.model.ChatRoom) {
with(chatRoom.chatRoom) {
val isDirectMessage = roomTypeOf(type) is RoomType.DirectMessage
val roomName = if (isDirectMessage
&& fullname != null
&& settings.useRealName()) {
fullname!!
} else {
val isChatRoomOwner = chatRoom.user?.username == myself.username || isDirectMessage
navigator.toChatRoom(chatRoom.id, roomName,
chatRoom.type.toString(), chatRoom.readonly ?: false,
chatRoom.lastSeen ?: -1,
chatRoom.open, isChatRoomOwner)
name
}
launchUI(strategy) {
val myself = getCurrentUser()
if (myself?.username == null) {
view.showMessage(R.string.msg_generic_error)
} else {
val isChatRoomOwner = ownerId == myself.id || isDirectMessage
navigator.toChatRoom(id, roomName, type, readonly ?: false,
lastSeen ?: -1, open, isChatRoomOwner)
}
}
}
}
......
......@@ -25,6 +25,7 @@ import chat.rocket.android.chatrooms.presentation.ChatRoomsPresenter
import chat.rocket.android.chatrooms.presentation.ChatRoomsView
import chat.rocket.android.chatrooms.viewmodel.ChatRoomsViewModel
import chat.rocket.android.chatrooms.viewmodel.ChatRoomsViewModelFactory
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.helper.ChatRoomsSortOrder
import chat.rocket.android.helper.Constants
import chat.rocket.android.helper.SharedPreferenceHelper
......@@ -39,6 +40,8 @@ import chat.rocket.core.internal.realtime.socket.model.State
import chat.rocket.core.model.ChatRoom
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_chat_rooms.*
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import timber.log.Timber
import javax.inject.Inject
......@@ -48,6 +51,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
@Inject
lateinit var factory: ChatRoomsViewModelFactory
@Inject
lateinit var dbManager: DatabaseManager // TODO - remove when moving ChatRoom screen to DB
lateinit var viewModel: ChatRoomsViewModel
private var searchView: SearchView? = null
......@@ -79,15 +85,25 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(this, factory).get(ChatRoomsViewModel::class.java)
val adapter = RoomsAdapter()
subscribeUi(adapter)
subscribeUi()
setupToolbar()
}
private fun subscribeUi(adapter: RoomsAdapter) {
private fun subscribeUi() {
ui {
val adapter = RoomsAdapter { roomId ->
launch(UI) {
dbManager.getRoom(roomId)?.let { room ->
ui {
presenter.loadChatRoom(room)
}
}
}
}
recycler_view.layoutManager = LinearLayoutManager(it, LinearLayoutManager.VERTICAL, false)
recycler_view.addItemDecoration(DividerItemDecoration(it,
resources.getDimensionPixelSize(R.dimen.divider_item_decorator_bound_start),
......@@ -102,6 +118,10 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
}
})
viewModel.getStatus().observe(viewLifecycleOwner, Observer { status ->
status?.let { showConnectionState(status) }
})
updateSort()
}
}
......
......@@ -8,16 +8,16 @@ import chat.rocket.android.chatrooms.adapter.ItemHolder
import chat.rocket.android.chatrooms.adapter.RoomMapper
import chat.rocket.android.chatrooms.domain.FetchChatRoomsInteractor
import chat.rocket.android.chatrooms.infrastructure.ChatRoomsRepository
import chat.rocket.android.db.model.ChatRoom
import kotlinx.coroutines.experimental.CommonPool
import chat.rocket.android.server.infraestructure.ConnectionManager
import chat.rocket.core.internal.realtime.socket.model.State
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext
import me.henrytao.livedataktx.distinct
import me.henrytao.livedataktx.nonNull
import me.henrytao.livedataktx.map
import me.henrytao.livedataktx.nonNull
import timber.log.Timber
class ChatRoomsViewModel(
private val connectionManager: ConnectionManager,
private val interactor: FetchChatRoomsInteractor,
private val repository: ChatRoomsRepository,
private val mapper: RoomMapper
......@@ -45,6 +45,10 @@ class ChatRoomsViewModel(
}
}
fun getStatus(): MutableLiveData<State> {
return connectionManager.statusLiveData.nonNull().distinct()
}
fun setOrdering(order: ChatRoomsRepository.Order) {
ordering.value = order
}
......
......@@ -5,9 +5,11 @@ import androidx.lifecycle.ViewModelProvider
import chat.rocket.android.chatrooms.adapter.RoomMapper
import chat.rocket.android.chatrooms.domain.FetchChatRoomsInteractor
import chat.rocket.android.chatrooms.infrastructure.ChatRoomsRepository
import chat.rocket.android.server.infraestructure.ConnectionManager
import javax.inject.Inject
class ChatRoomsViewModelFactory @Inject constructor(
private val connectionManager: ConnectionManager,
private val interactor: FetchChatRoomsInteractor,
private val repository: ChatRoomsRepository,
private val mapper: RoomMapper
......@@ -15,5 +17,5 @@ class ChatRoomsViewModelFactory @Inject constructor(
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>) =
ChatRoomsViewModel(interactor, repository, mapper) as T
ChatRoomsViewModel(connectionManager, interactor, repository, mapper) as T
}
\ No newline at end of file
......@@ -18,8 +18,31 @@ import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.SharedPreferencesLocalRepository
import chat.rocket.android.push.GroupedPush
import chat.rocket.android.push.PushManager
import chat.rocket.android.server.domain.*
import chat.rocket.android.server.infraestructure.*
import chat.rocket.android.server.domain.AccountsRepository
import chat.rocket.android.server.domain.ActiveUsersRepository
import chat.rocket.android.server.domain.ChatRoomsRepository
import chat.rocket.android.server.domain.CurrentServerRepository
import chat.rocket.android.server.domain.GetAccountInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.JobSchedulerInteractor
import chat.rocket.android.server.domain.MessagesRepository
import chat.rocket.android.server.domain.MultiServerTokenRepository
import chat.rocket.android.server.domain.PermissionsRepository
import chat.rocket.android.server.domain.RoomRepository
import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.UsersRepository
import chat.rocket.android.server.infraestructure.JobSchedulerInteractorImpl
import chat.rocket.android.server.infraestructure.MemoryActiveUsersRepository
import chat.rocket.android.server.infraestructure.MemoryChatRoomsRepository
import chat.rocket.android.server.infraestructure.MemoryRoomRepository
import chat.rocket.android.server.infraestructure.MemoryUsersRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesAccountsRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesMessagesRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesPermissionsRepository
import chat.rocket.android.server.infraestructure.SharedPreferencesSettingsRepository
import chat.rocket.android.server.infraestructure.SharedPrefsCurrentServerRepository
import chat.rocket.android.util.AppJsonAdapterFactory
import chat.rocket.android.util.TimberLogger
import chat.rocket.common.internal.FallbackSealedClassJsonAdapter
......@@ -28,7 +51,6 @@ import chat.rocket.common.model.TimestampAdapter
import chat.rocket.common.util.CalendarISO8601Converter
import chat.rocket.common.util.Logger
import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.AttachmentAdapterFactory
import chat.rocket.core.internal.ReactionsAdapter
import com.facebook.drawee.backends.pipeline.DraweeConfig
......@@ -38,7 +60,6 @@ import com.facebook.imagepipeline.listener.RequestLoggingListener
import com.squareup.moshi.Moshi
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import ru.noties.markwon.SpannableConfiguration
......@@ -50,24 +71,6 @@ import javax.inject.Singleton
@Module
class AppModule {
/*@Provides
@Singleton
fun provideRocketChatClient(okHttpClient: OkHttpClient, repository: TokenRepository, logger: PlatformLogger): RocketChatClient {
return RocketChatClient.create {
httpClient = okHttpClient
tokenRepository = repository
platformLogger = logger
// TODO remove
restUrl = "https://open.rocket.chat"
}
}*/
@Provides
fun provideJob(): Job {
return Job()
}
@Provides
@Singleton
fun provideContext(application: Application): Context {
......@@ -109,7 +112,6 @@ class AppModule {
return OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient)
.setRequestListeners(listeners)
.setDownsampleEnabled(true)
//.experiment().setBitmapPrepareToDraw(true).experiment()
.experiment().setPartialImageCachingEnabled(true).build()
}
......
......@@ -13,6 +13,13 @@ import chat.rocket.common.model.RoomType
@Dao
abstract class ChatRoomDao : BaseDao<ChatRoomEntity> {
@Transaction
@Query("""
$BASE_QUERY
WHERE chatrooms.id = :id
""")
abstract fun get(id: String): ChatRoom?
@Transaction
@Query("""
$BASE_QUERY
......@@ -52,9 +59,6 @@ abstract class ChatRoomDao : BaseDao<ChatRoomEntity> {
""")
abstract fun getAllAlphabeticallyGrouped(): LiveData<List<ChatRoom>>
@Query("SELECT * FROM chatrooms WHERE ID = :id")
abstract fun get(id: String): ChatRoom?
@Query("DELETE FROM chatrooms WHERE ID = :id")
abstract fun delete(id: String)
......
......@@ -2,6 +2,7 @@ package chat.rocket.android.db
import android.app.Application
import chat.rocket.android.db.model.BaseUserEntity
import chat.rocket.android.db.model.ChatRoom
import chat.rocket.android.db.model.ChatRoomEntity
import chat.rocket.android.db.model.UserEntity
import chat.rocket.android.db.model.UserStatus
......@@ -35,6 +36,10 @@ class DatabaseManager(val context: Application,
fun chatRoomDao(): ChatRoomDao = database.chatRoomDao()
fun userDao(): UserDao = database.userDao()
suspend fun getRoom(id: String) = withContext(dbContext) {
chatRoomDao().get(id)
}
fun processUsersBatch(users: List<User>) {
launch(dbContext) {
val dao = database.userDao()
......@@ -152,8 +157,17 @@ class DatabaseManager(val context: Application,
}
}
user?.let { user ->
if (findUser(user.id!!) == null) {
Timber.d("Missing owner user, inserting: ${user.id}")
insert(UserEntity(user.id!!, user.username, user.name))
}
}
chatRoom.copy(
name = name ?: chatRoom.name,
fullname = fullName ?: chatRoom.fullname,
ownerId = user?.id ?: chatRoom.ownerId,
readonly = readonly,
updatedAt = updatedAt ?: chatRoom.updatedAt,
lastMessageText = lastMessage?.message,
......@@ -186,6 +200,7 @@ class DatabaseManager(val context: Application,
subscriptionId = id,
type = type.toString(),
name = name,
fullname = fullName ?: chatRoom.fullname,
userId = userId ?: chatRoom.userId,
readonly = readonly ?: chatRoom.readonly,
isDefault = isDefault,
......@@ -249,12 +264,21 @@ class DatabaseManager(val context: Application,
}
}
room.user?.let { user ->
if (findUser(user.id!!) == null) {
Timber.d("Missing owner user, inserting: ${user.id}")
insert(UserEntity(user.id!!, user.username, user.name))
}
}
return ChatRoomEntity(
id = room.id,
subscriptionId = subscription.id,
type = room.type.toString(),
name = room.name ?: subscription.name,
fullname = subscription.fullName ?: room.fullName,
userId = userId,
ownerId = room.user?.id,
readonly = subscription.readonly,
isDefault = subscription.isDefault,
favorite = subscription.isFavorite,
......
......@@ -7,7 +7,7 @@ import chat.rocket.android.db.model.UserEntity
@Database(
entities = [UserEntity::class, ChatRoomEntity::class],
version = 1,
version = 2,
exportSchema = true
)
abstract class RCDatabase : RoomDatabase() {
......
......@@ -9,10 +9,12 @@ import androidx.room.PrimaryKey
@Entity(tableName = "chatrooms",
indices = [
Index(value = ["userId"]),
Index(value = ["ownerId"]),
Index(value = ["subscriptionId"], unique = true),
Index(value = ["updatedAt"])
],
foreignKeys = [
ForeignKey(entity = UserEntity::class, parentColumns = ["id"], childColumns = ["ownerId"]),
ForeignKey(entity = UserEntity::class, parentColumns = ["id"], childColumns = ["userId"]),
ForeignKey(entity = UserEntity::class, parentColumns = ["id"], childColumns = ["lastMessageUserId"])
]
......@@ -22,7 +24,9 @@ data class ChatRoomEntity(
var subscriptionId: String,
var type: String,
var name: String,
var fullname: String?,
var userId: String?,
var ownerId: String?,
var readonly: Boolean? = false,
var isDefault: Boolean? = false,
var favorite: Boolean? = false,
......
......@@ -4,6 +4,7 @@ import androidx.lifecycle.LifecycleOwner
import android.content.Context
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.main.presentation.MainView
import chat.rocket.android.main.ui.MainActivity
......@@ -14,6 +15,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class MainModule {
@Provides
@PerActivity
fun provideJob() = Job()
@Provides
@PerActivity
fun provideMainNavigator(activity: MainActivity) = MainNavigator(activity)
......
......@@ -14,6 +14,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class MembersFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun provideChatRoomNavigator(activity: ChatRoomActivity) = MembersNavigator(activity)
......
......@@ -12,6 +12,10 @@ import kotlinx.coroutines.experimental.Job
@Module
class PinnedMessagesFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun provideLifecycleOwner(frag: PinnedMessagesFragment): LifecycleOwner {
......
......@@ -3,6 +3,7 @@ package chat.rocket.android.server.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.server.presentation.ChangeServerNavigator
import chat.rocket.android.server.presentation.ChangeServerView
import chat.rocket.android.server.ui.ChangeServerActivity
......@@ -12,6 +13,11 @@ import kotlinx.coroutines.experimental.Job
@Module
class ChangeServerModule {
@Provides
@PerActivity
fun provideJob() = Job()
@Provides
@PerActivity
fun provideChangeServerNavigator(activity: ChangeServerActivity) = ChangeServerNavigator(activity)
......
......@@ -35,7 +35,7 @@ class ConnectionManager(
internal val client: RocketChatClient,
private val dbManager: DatabaseManager
) {
private val statusLiveData = MutableLiveData<State>()
val statusLiveData = MutableLiveData<State>()
private val statusChannelList = CopyOnWriteArrayList<Channel<State>>()
private val statusChannel = Channel<State>(Channel.CONFLATED)
private var connectJob: Job? = null
......
......@@ -11,6 +11,11 @@ import kotlinx.coroutines.experimental.Job
@Module
class PasswordFragmentModule {
@Provides
@PerFragment
fun provideJob() = Job()
@Provides
@PerFragment
fun passwordView(frag: PasswordFragment): PasswordView {
......
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