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,
"database": {
"version": 13,
"identityHash": "a521f027909f69f4c7d1855f84a2e67f",
"identityHash": "f58d9b51b48ddc5c6f4dc4c742eb5f3f",
"entities": [
{
"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": [],
"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, '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.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import autodagger.AutoInjector
import com.google.android.material.snackbar.Snackbar
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.chat.ChatActivity
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.databinding.ActivityMainBinding
import com.nextcloud.talk.invitation.InvitationsActivity
@ -46,6 +48,7 @@ import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -58,6 +61,9 @@ class MainActivity : BaseActivity(), ActionBarProvider {
@Inject
lateinit var userManager: UserManager
@Inject
lateinit var userGroupsOrCirclesRepository: UserGroupsCirclesRepository
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
finish()
@ -146,6 +152,10 @@ class MainActivity : BaseActivity(), ActionBarProvider {
}
private fun handleActionFromContact(intent: Intent) {
lifecycleScope.launch {
val initialized = userGroupsOrCirclesRepository.initialize()
Log.d("MainActivity", "$initialized")
}
if (intent.action == Intent.ACTION_VIEW && intent.data != 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() {

View File

@ -50,9 +50,6 @@ import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
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.catch
import kotlinx.coroutines.flow.first
@ -236,12 +233,6 @@ class ChatViewModel @Inject constructor(
val leaveRoomViewState: LiveData<ViewState>
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 ChatMessageStartState : ViewState
object ChatMessageUpdateState : ViewState
@ -364,13 +355,6 @@ class ChatViewModel @Inject constructor(
_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) {
chatNetworkDataSource.deleteReminder(user, roomToken, messageId, chatApiVersion)
.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.ChatMessagesDao
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 dagger.Module
import dagger.Provides
@ -24,4 +25,7 @@ internal object DaosModule {
@Provides
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.ChatMessagesDao
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.source.local.TalkDatabase
import com.nextcloud.talk.data.storage.ArbitraryStoragesRepository
@ -186,4 +188,13 @@ class RepositoryModule {
ncApiCoroutines: NcApiCoroutines,
currentUserProviderNew: 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 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.PlatformPermissionUtilImpl
import dagger.Module
@ -29,10 +28,4 @@ class UtilsModule {
fun provideDateUtils(context: Context): DateUtils {
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.ChatMessagesDao
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.ChatMessageEntity
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.CapabilitiesConverter
import com.nextcloud.talk.data.source.local.converters.ExternalSignalingServerConverter
@ -47,7 +50,9 @@ import java.util.Locale
ArbitraryStorageEntity::class,
ConversationEntity::class,
ChatMessageEntity::class,
ChatBlockEntity::class
ChatBlockEntity::class,
UserCirclesEntity:: class,
UserGroupsEntity::class
],
version = 16,
autoMigrations = [
@ -72,6 +77,7 @@ abstract class TalkDatabase : RoomDatabase() {
abstract fun chatMessagesDao(): ChatMessagesDao
abstract fun chatBlocksDao(): ChatBlocksDao
abstract fun arbitraryStoragesDao(): ArbitraryStoragesDao
abstract fun userCirclesOrGroupsDao(): UserCirclesOrGroupsDao
companion object {
const val TAG = "TalkDatabase"