store user groups and circles in room database

Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com>
This commit is contained in:
sowjanyakch 2025-03-18 22:33:02 +01:00
parent d3051325d3
commit acee0a5545
No known key found for this signature in database
GPG Key ID: F7AA2A8B65B50220
12 changed files with 221 additions and 37 deletions

View File

@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 13, "version": 13,
"identityHash": "a521f027909f69f4c7d1855f84a2e67f", "identityHash": "f58d9b51b48ddc5c6f4dc4c742eb5f3f",
"entities": [ "entities": [
{ {
"tableName": "User", "tableName": "User",
@ -738,12 +738,52 @@
] ]
} }
] ]
},
{
"tableName": "user_circles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`displayName` TEXT NOT NULL, PRIMARY KEY(`displayName`))",
"fields": [
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"displayName"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "user_groups",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groups` TEXT NOT NULL, PRIMARY KEY(`groups`))",
"fields": [
{
"fieldPath": "groups",
"columnName": "groups",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"groups"
]
},
"indices": [],
"foreignKeys": []
} }
], ],
"views": [], "views": [],
"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, 'a521f027909f69f4c7d1855f84a2e67f')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f58d9b51b48ddc5c6f4dc4c742eb5f3f')"
] ]
} }
} }

View File

@ -21,6 +21,7 @@ import androidx.activity.OnBackPressedCallback
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import autodagger.AutoInjector import autodagger.AutoInjector
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.nextcloud.talk.R import com.nextcloud.talk.R
@ -30,6 +31,7 @@ import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.chat.ChatActivity import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.conversationlist.ConversationsListActivity
import com.nextcloud.talk.data.database.model.UserGroupsCirclesRepository
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ActivityMainBinding import com.nextcloud.talk.databinding.ActivityMainBinding
import com.nextcloud.talk.invitation.InvitationsActivity import com.nextcloud.talk.invitation.InvitationsActivity
@ -46,6 +48,7 @@ import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
@ -58,6 +61,9 @@ class MainActivity : BaseActivity(), ActionBarProvider {
@Inject @Inject
lateinit var userManager: UserManager lateinit var userManager: UserManager
@Inject
lateinit var userGroupsOrCirclesRepository: UserGroupsCirclesRepository
private val onBackPressedCallback = object : OnBackPressedCallback(true) { private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() { override fun handleOnBackPressed() {
finish() finish()
@ -146,6 +152,10 @@ class MainActivity : BaseActivity(), ActionBarProvider {
} }
private fun handleActionFromContact(intent: Intent) { private fun handleActionFromContact(intent: Intent) {
lifecycleScope.launch {
val initialized = userGroupsOrCirclesRepository.initialize()
Log.d("MainActivity", "$initialized")
}
if (intent.action == Intent.ACTION_VIEW && intent.data != null) { if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
val cursor = contentResolver.query(intent.data!!, null, null, null, null) val cursor = contentResolver.query(intent.data!!, null, null, null, null)

View File

@ -1212,17 +1212,6 @@ class ChatActivity :
} }
} }
} }
lifecycleScope.launch {
chatViewModel.userGroups.collect { userGroups ->
messageUtils.setUserGroups(userGroups)
}
}
lifecycleScope.launch {
chatViewModel.userCircles.collect { userCircles ->
messageUtils.setUserCircles(userCircles)
}
}
} }
private fun removeUnreadMessagesMarker() { private fun removeUnreadMessagesMarker() {

View File

@ -50,9 +50,6 @@ import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@ -236,12 +233,6 @@ class ChatViewModel @Inject constructor(
val leaveRoomViewState: LiveData<ViewState> val leaveRoomViewState: LiveData<ViewState>
get() = _leaveRoomViewState get() = _leaveRoomViewState
private val _userGroups = MutableStateFlow<Set<String>>(emptySet())
val userGroups: StateFlow<Set<String>> = _userGroups.asStateFlow()
private val _userCircles = MutableStateFlow<Set<String>>(emptySet())
val userCircles: StateFlow<Set<String>> = _userCircles.asStateFlow()
object ChatMessageInitialState : ViewState object ChatMessageInitialState : ViewState
object ChatMessageStartState : ViewState object ChatMessageStartState : ViewState
object ChatMessageUpdateState : ViewState object ChatMessageUpdateState : ViewState
@ -364,13 +355,6 @@ class ChatViewModel @Inject constructor(
_getReminderExistState.value = GetReminderStateSet _getReminderExistState.value = GetReminderStateSet
} }
fun fetchUserData(user: User) {
viewModelScope.launch {
_userGroups.value = chatNetworkDataSource.getUserGroups(user)
_userCircles.value = chatNetworkDataSource.getUserCircles(user)
}
}
fun deleteReminder(user: User, roomToken: String, messageId: String, chatApiVersion: Int) { fun deleteReminder(user: User, roomToken: String, messageId: String, chatApiVersion: Int) {
chatNetworkDataSource.deleteReminder(user, roomToken, messageId, chatApiVersion) chatNetworkDataSource.deleteReminder(user, roomToken, messageId, chatApiVersion)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())

View File

@ -10,6 +10,7 @@ package com.nextcloud.talk.dagger.modules
import com.nextcloud.talk.data.database.dao.ChatBlocksDao import com.nextcloud.talk.data.database.dao.ChatBlocksDao
import com.nextcloud.talk.data.database.dao.ChatMessagesDao import com.nextcloud.talk.data.database.dao.ChatMessagesDao
import com.nextcloud.talk.data.database.dao.ConversationsDao import com.nextcloud.talk.data.database.dao.ConversationsDao
import com.nextcloud.talk.data.database.dao.UserCirclesOrGroupsDao
import com.nextcloud.talk.data.source.local.TalkDatabase import com.nextcloud.talk.data.source.local.TalkDatabase
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@ -24,4 +25,7 @@ internal object DaosModule {
@Provides @Provides
fun providesChatBlocksDao(database: TalkDatabase): ChatBlocksDao = database.chatBlocksDao() fun providesChatBlocksDao(database: TalkDatabase): ChatBlocksDao = database.chatBlocksDao()
@Provides
fun providesUserCirclesOrGroups(database: TalkDatabase): UserCirclesOrGroupsDao = database.userCirclesOrGroupsDao()
} }

View File

@ -28,6 +28,8 @@ import com.nextcloud.talk.conversationlist.data.network.RetrofitConversationsNet
import com.nextcloud.talk.data.database.dao.ChatBlocksDao import com.nextcloud.talk.data.database.dao.ChatBlocksDao
import com.nextcloud.talk.data.database.dao.ChatMessagesDao import com.nextcloud.talk.data.database.dao.ChatMessagesDao
import com.nextcloud.talk.data.database.dao.ConversationsDao import com.nextcloud.talk.data.database.dao.ConversationsDao
import com.nextcloud.talk.data.database.dao.UserCirclesOrGroupsDao
import com.nextcloud.talk.data.database.model.UserGroupsCirclesRepository
import com.nextcloud.talk.data.network.NetworkMonitor import com.nextcloud.talk.data.network.NetworkMonitor
import com.nextcloud.talk.data.source.local.TalkDatabase import com.nextcloud.talk.data.source.local.TalkDatabase
import com.nextcloud.talk.data.storage.ArbitraryStoragesRepository import com.nextcloud.talk.data.storage.ArbitraryStoragesRepository
@ -186,4 +188,13 @@ class RepositoryModule {
ncApiCoroutines: NcApiCoroutines, ncApiCoroutines: NcApiCoroutines,
currentUserProviderNew: CurrentUserProviderNew currentUserProviderNew: CurrentUserProviderNew
): ConversationCreationRepository = ConversationCreationRepositoryImpl(ncApiCoroutines, currentUserProviderNew) ): ConversationCreationRepository = ConversationCreationRepositoryImpl(ncApiCoroutines, currentUserProviderNew)
@Provides
fun provideUserGroupsCirclesRepository(
userCirclesOrGroupsDao: UserCirclesOrGroupsDao,
ncApiCoroutines: NcApiCoroutines,
userProvider: CurrentUserProviderNew
): UserGroupsCirclesRepository {
return UserGroupsCirclesRepository(userCirclesOrGroupsDao, ncApiCoroutines, userProvider)
}
} }

View File

@ -9,7 +9,6 @@ package com.nextcloud.talk.dagger.modules
import android.content.Context import android.content.Context
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
import com.nextcloud.talk.utils.permissions.PlatformPermissionUtilImpl import com.nextcloud.talk.utils.permissions.PlatformPermissionUtilImpl
import dagger.Module import dagger.Module
@ -29,10 +28,4 @@ class UtilsModule {
fun provideDateUtils(context: Context): DateUtils { fun provideDateUtils(context: Context): DateUtils {
return DateUtils(context) return DateUtils(context)
} }
@Provides
@Reusable
fun provideMessageUtils(context: Context): MessageUtils {
return MessageUtils(context)
}
} }

View File

@ -0,0 +1,32 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.data.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.nextcloud.talk.data.database.model.UserCirclesEntity
import com.nextcloud.talk.data.database.model.UserGroupsEntity
@Dao
interface UserCirclesOrGroupsDao {
@Query("SELECT groups FROM user_groups")
fun getUserGroups(): List<UserGroupsEntity>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUserGroups(groups:List<UserGroupsEntity>)
@Query("SELECT displayName FROM user_circles")
fun getUserCircles(): List<UserCirclesEntity>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUserCircles(circles: List<UserCirclesEntity>)
}

View File

@ -0,0 +1,19 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.data.database.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "user_circles")
data class UserCirclesEntity(
@PrimaryKey
@ColumnInfo(name = "displayName")
var displayName: String,
)

View File

@ -0,0 +1,78 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.data.database.model
import android.util.Log
import com.nextcloud.talk.api.NcApiCoroutines
import com.nextcloud.talk.data.database.dao.UserCirclesOrGroupsDao
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
class UserGroupsCirclesRepository @Inject constructor(
private val userCirclesOrGroupsDao: UserCirclesOrGroupsDao,
private val ncApiCoroutines: NcApiCoroutines,
private val currentUserProvider: CurrentUserProviderNew
) {
val user = currentUserProvider.currentUser.blockingGet()
suspend fun initialize(): Boolean = withContext(Dispatchers.IO) {
try {
val credentials: String = ApiUtils.getCredentials(user.username, user.token)!!
coroutineScope {
launch {
val response = ncApiCoroutines.getUserGroups(
credentials,
ApiUtils.getUrlForUserGroups(
user.baseUrl!!,
user.userId!!
)
)
val groups = response.ocs?.data?.groups?: emptyList()
userCirclesOrGroupsDao.insertUserGroups(
groups.map{
UserGroupsEntity(it)
}
)
}
launch {
val response = ncApiCoroutines.getUserCircles(
credentials,
ApiUtils.getUrlForUserCircles(user.baseUrl!!)
)
val circles = response.ocs?.data?.map { it.displayName!! }?: emptyList()
userCirclesOrGroupsDao.insertUserCircles(
circles.map{
UserCirclesEntity(it)
}
)
}
}
return@withContext true
} catch (e: Exception) {
Log.e("UserDataRepo", "Error initializing user data", e)
return@withContext false
}
}
fun getUserGroups(): List<UserGroupsEntity> {
return userCirclesOrGroupsDao.getUserGroups()
}
fun getUserCircles(): List<UserCirclesEntity> {
return userCirclesOrGroupsDao.getUserCircles()
}
}

View File

@ -0,0 +1,18 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.data.database.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "user_groups")
data class UserGroupsEntity(
@PrimaryKey
@ColumnInfo (name="groups") var groups: String,
)

View File

@ -20,9 +20,12 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.data.database.dao.ChatBlocksDao import com.nextcloud.talk.data.database.dao.ChatBlocksDao
import com.nextcloud.talk.data.database.dao.ChatMessagesDao import com.nextcloud.talk.data.database.dao.ChatMessagesDao
import com.nextcloud.talk.data.database.dao.ConversationsDao import com.nextcloud.talk.data.database.dao.ConversationsDao
import com.nextcloud.talk.data.database.dao.UserCirclesOrGroupsDao
import com.nextcloud.talk.data.database.model.ChatBlockEntity import com.nextcloud.talk.data.database.model.ChatBlockEntity
import com.nextcloud.talk.data.database.model.ChatMessageEntity import com.nextcloud.talk.data.database.model.ChatMessageEntity
import com.nextcloud.talk.data.database.model.ConversationEntity import com.nextcloud.talk.data.database.model.ConversationEntity
import com.nextcloud.talk.data.database.model.UserCirclesEntity
import com.nextcloud.talk.data.database.model.UserGroupsEntity
import com.nextcloud.talk.data.source.local.converters.ArrayListConverter import com.nextcloud.talk.data.source.local.converters.ArrayListConverter
import com.nextcloud.talk.data.source.local.converters.CapabilitiesConverter import com.nextcloud.talk.data.source.local.converters.CapabilitiesConverter
import com.nextcloud.talk.data.source.local.converters.ExternalSignalingServerConverter import com.nextcloud.talk.data.source.local.converters.ExternalSignalingServerConverter
@ -47,7 +50,9 @@ import java.util.Locale
ArbitraryStorageEntity::class, ArbitraryStorageEntity::class,
ConversationEntity::class, ConversationEntity::class,
ChatMessageEntity::class, ChatMessageEntity::class,
ChatBlockEntity::class ChatBlockEntity::class,
UserCirclesEntity:: class,
UserGroupsEntity::class
], ],
version = 16, version = 16,
autoMigrations = [ autoMigrations = [
@ -72,6 +77,7 @@ abstract class TalkDatabase : RoomDatabase() {
abstract fun chatMessagesDao(): ChatMessagesDao abstract fun chatMessagesDao(): ChatMessagesDao
abstract fun chatBlocksDao(): ChatBlocksDao abstract fun chatBlocksDao(): ChatBlocksDao
abstract fun arbitraryStoragesDao(): ArbitraryStoragesDao abstract fun arbitraryStoragesDao(): ArbitraryStoragesDao
abstract fun userCirclesOrGroupsDao(): UserCirclesOrGroupsDao
companion object { companion object {
const val TAG = "TalkDatabase" const val TAG = "TalkDatabase"