Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com>
This commit is contained in:
sowjanyakch 2025-03-20 17:33:21 +01:00
parent 17f4a20cbd
commit e874502d8c
No known key found for this signature in database
GPG Key ID: F7AA2A8B65B50220
14 changed files with 129 additions and 58 deletions

View File

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

View File

@ -21,7 +21,6 @@ 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
@ -31,7 +30,6 @@ 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
@ -48,8 +46,6 @@ import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -61,10 +57,6 @@ class MainActivity : BaseActivity(), ActionBarProvider {
@Inject
lateinit var userManager: UserManager
private var job: Job? = null
@Inject
lateinit var userGroupsOrCirclesRepository: UserGroupsCirclesRepository
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
@ -94,11 +86,6 @@ class MainActivity : BaseActivity(), ActionBarProvider {
handleIntent(intent)
job = lifecycleScope.launch {
val initialized = userGroupsOrCirclesRepository.initialize()
Log.d("MainActivity", "$initialized")
}
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
}
@ -153,7 +140,6 @@ class MainActivity : BaseActivity(), ActionBarProvider {
override fun onDestroy() {
super.onDestroy()
job?.cancel()
}
private fun openConversationList() {

View File

@ -83,7 +83,9 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) :
viewThemeUtils,
processedMessageText!!,
message,
itemView
itemView,
null,
null
)
binding.messageText.text = processedMessageText

View File

@ -60,7 +60,9 @@ public class IncomingPreviewMessageViewHolder extends PreviewMessageViewHolder {
viewThemeUtils,
processedMessageText,
message,
binding.incomingPreviewMessageBubble);
binding.incomingPreviewMessageBubble,
null,
null);
}
binding.incomingPreviewMessageBubble.setOnClickListener(null);

View File

@ -27,6 +27,7 @@ import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.chat.data.ChatMessageRepository
import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.data.database.model.UserGroupsCirclesRepository
import com.nextcloud.talk.databinding.ItemCustomIncomingTextMessageBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
@ -43,6 +44,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Date
@ -74,6 +77,11 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
lateinit var commonMessageInterface: CommonMessageInterface
@Inject
lateinit var userGroupsCirclesRepository: UserGroupsCirclesRepository
private val coroutineScope = CoroutineScope(Dispatchers.Main)
@Inject
lateinit var chatRepository: ChatMessageRepository
@ -95,7 +103,14 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
private fun processMessage(message: ChatMessage, hasCheckboxes: Boolean) {
var textSize = context.resources!!.getDimension(R.dimen.chat_text_size)
if (!hasCheckboxes) {
coroutineScope.launch {
val userGroups = userGroupsCirclesRepository.getUserGroups()
.map { list -> list.mapNotNull { it.groups } }.firstOrNull() ?: emptyList()
val userCircles = userGroupsCirclesRepository.getUserCircles()
.map { list -> list.mapNotNull { it.displayName } }.firstOrNull() ?: emptyList()
if (!hasCheckboxes) {
binding.messageText.visibility = View.VISIBLE
binding.checkboxContainer.visibility = View.GONE
var processedMessageText = messageUtils.enrichChatMessageText(
@ -132,7 +147,9 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
viewThemeUtils,
processedMessageText,
message,
itemView
itemView,
userGroups,
userCircles
)
val messageParameters = message.messageParameters
if (
@ -178,6 +195,7 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
viewThemeUtils
)
}
}
private fun processCheckboxes(chatMessage: ChatMessage, user: User): Boolean {
val chatActivity = commonMessageInterface as ChatActivity

View File

@ -83,7 +83,9 @@ class OutcomingLinkPreviewMessageViewHolder(outcomingView: View, payload: Any) :
viewThemeUtils,
processedMessageText!!,
message,
itemView
itemView,
null,
null
)
binding.messageText.text = processedMessageText

View File

@ -60,7 +60,9 @@ public class OutcomingPreviewMessageViewHolder extends PreviewMessageViewHolder
viewThemeUtils,
processedMessageText,
message,
binding.outgoingPreviewMessageBubble);
binding.outgoingPreviewMessageBubble,
null,
null);
}
binding.outgoingPreviewMessageBubble.setOnClickListener(null);

View File

@ -29,6 +29,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA
import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.chat.data.ChatMessageRepository
import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.data.database.model.UserGroupsCirclesRepository
import com.nextcloud.talk.data.network.NetworkMonitor
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ItemCustomOutcomingTextMessageBinding
@ -47,6 +48,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Date
@ -85,6 +88,11 @@ class OutcomingTextMessageViewHolder(itemView: View) :
private var job: Job? = null
@Inject
lateinit var userGroupsCirclesRepository: UserGroupsCirclesRepository
private val coroutineScope = CoroutineScope(Dispatchers.Main)
@Suppress("Detekt.LongMethod")
override fun onBind(message: ChatMessage) {
super.onBind(message)
@ -106,6 +114,13 @@ class OutcomingTextMessageViewHolder(itemView: View) :
realView.isSelected = false
layoutParams.isWrapBefore = false
viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT)
viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT)
coroutineScope.launch {
val userGroups = userGroupsCirclesRepository.getUserGroups()
.map { list -> list.mapNotNull { it.groups } }.firstOrNull() ?: emptyList()
val userCircles = userGroupsCirclesRepository.getUserCircles()
.map { list -> list.mapNotNull { it.displayName } }.firstOrNull() ?: emptyList()
binding.messageText.visibility = View.VISIBLE
binding.checkboxContainer.visibility = View.GONE
@ -114,7 +129,8 @@ class OutcomingTextMessageViewHolder(itemView: View) :
binding.messageText.context,
message,
false,
viewThemeUtils
viewThemeUtils,
)
val spansFromString: Array<Any> = processedMessageText!!.getSpans(
@ -144,8 +160,13 @@ class OutcomingTextMessageViewHolder(itemView: View) :
viewThemeUtils,
processedMessageText,
message,
itemView
itemView,
userGroups,
userCircles
)
binding.messageText.text = processedMessageText
}
if (
(message.messageParameters == null || message.messageParameters!!.size <= 0) &&
@ -220,6 +241,7 @@ class OutcomingTextMessageViewHolder(itemView: View) :
)
}
private fun processCheckboxes(chatMessage: ChatMessage, user: User): Boolean {
val chatActivity = commonMessageInterface as ChatActivity
val message = chatMessage.message!!.toSpanned()

View File

@ -89,6 +89,7 @@ import com.nextcloud.talk.contacts.ContactsUiState
import com.nextcloud.talk.contacts.ContactsViewModel
import com.nextcloud.talk.contacts.RoomUiState
import com.nextcloud.talk.conversationlist.viewmodels.ConversationsListViewModel
import com.nextcloud.talk.data.database.model.UserGroupsCirclesRepository
import com.nextcloud.talk.data.network.NetworkMonitor
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ActivityConversationsBinding
@ -152,6 +153,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.BehaviorSubject
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -202,6 +204,11 @@ class ConversationsListActivity :
lateinit var conversationsListViewModel: ConversationsListViewModel
private var job: Job? = null
@Inject
lateinit var userGroupsOrCirclesRepository: UserGroupsCirclesRepository
override val appBarLayoutType: AppBarLayoutType
get() = AppBarLayoutType.SEARCH_BAR
@ -271,6 +278,11 @@ class ConversationsListActivity :
forwardMessage = intent.getBooleanExtra(KEY_FORWARD_MSG_FLAG, false)
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
job = lifecycleScope.launch {
val initialized = userGroupsOrCirclesRepository.initialize()
Log.d("MainActivity", "$initialized")
}
initObservers()
}
@ -1355,6 +1367,7 @@ class ConversationsListActivity :
if (searchViewDisposable != null && !searchViewDisposable!!.isDisposed) {
searchViewDisposable!!.dispose()
}
job?.cancel()
}
private fun onQueryTextChange(newText: String?) {

View File

@ -13,18 +13,19 @@ import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.nextcloud.talk.data.database.model.UserCirclesEntity
import com.nextcloud.talk.data.database.model.UserGroupsEntity
import kotlinx.coroutines.flow.Flow
@Dao
interface UserCirclesOrGroupsDao {
@Query("SELECT groups FROM user_groups")
fun getUserGroups(): List<UserGroupsEntity>
@Query("SELECT * FROM user_groups")
fun getUserGroups(): Flow<List<UserGroupsEntity>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUserGroups(groups: List<UserGroupsEntity>)
@Query("SELECT displayName FROM user_circles")
fun getUserCircles(): List<UserCirclesEntity>
@Query("SELECT * FROM user_circles")
fun getUserCircles(): Flow<List<UserCirclesEntity>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUserCircles(circles: List<UserCirclesEntity>)

View File

@ -10,10 +10,13 @@ package com.nextcloud.talk.data.database.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import javax.annotation.Nonnull
@Entity(tableName = "user_circles")
data class UserCirclesEntity(
@PrimaryKey
@Nonnull
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id") var id: Int = 0,
@ColumnInfo(name = "displayName")
var displayName: String
var displayName: String?
)

View File

@ -14,6 +14,7 @@ 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.flow.Flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@ -23,12 +24,12 @@ class UserGroupsCirclesRepository @Inject constructor(
private val ncApiCoroutines: NcApiCoroutines,
private val currentUserProvider: CurrentUserProviderNew
) {
val user = currentUserProvider.currentUser.blockingGet()
@Suppress("Detekt.TooGenericExceptionCaught")
suspend fun initialize(): Boolean =
withContext(Dispatchers.IO) {
try {
val user = currentUserProvider.currentUser.blockingGet()
val credentials: String = ApiUtils.getCredentials(user.username, user.token)!!
coroutineScope {
@ -45,7 +46,7 @@ class UserGroupsCirclesRepository @Inject constructor(
Log.d("UserDataRepo", "$groups")
userCirclesOrGroupsDao.insertUserGroups(
groups.map {
UserGroupsEntity(it)
UserGroupsEntity(id = 0, it)
}
)
}
@ -60,24 +61,17 @@ class UserGroupsCirclesRepository @Inject constructor(
Log.d("UserDataRepo", "$circles")
userCirclesOrGroupsDao.insertUserCircles(
circles.map {
UserCirclesEntity(it)
UserCirclesEntity(id = 0, 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()
}
fun getUserGroups(): Flow<List<UserGroupsEntity>> = userCirclesOrGroupsDao.getUserGroups()
fun getUserCircles(): Flow<List<UserCirclesEntity>> = userCirclesOrGroupsDao.getUserCircles()
}

View File

@ -10,9 +10,12 @@ package com.nextcloud.talk.data.database.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import javax.annotation.Nonnull
@Entity(tableName = "user_groups")
data class UserGroupsEntity(
@PrimaryKey
@ColumnInfo(name = "groups") var groups: String
@Nonnull
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id") var id: Int = 0,
@ColumnInfo(name = "groups") var groups: String?
)

View File

@ -28,8 +28,9 @@ import io.noties.markwon.ext.strikethrough.StrikethroughPlugin
import io.noties.markwon.ext.tables.TablePlugin
import io.noties.markwon.ext.tasklist.TaskListDrawable
import io.noties.markwon.ext.tasklist.TaskListPlugin
import javax.inject.Inject
class MessageUtils(val context: Context) {
class MessageUtils @Inject constructor(val context: Context) {
fun enrichChatReplyMessageText(
context: Context,
@ -81,7 +82,9 @@ class MessageUtils(val context: Context) {
viewThemeUtils: ViewThemeUtils,
spannedText: Spanned,
message: ChatMessage,
itemView: View?
itemView: View?,
userGroups: List<String>?,
userCircles: List<String>?
): Spanned {
var processedMessageText = spannedText
val messageParameters = message.messageParameters
@ -92,7 +95,10 @@ class MessageUtils(val context: Context) {
messageParameters,
message,
processedMessageText,
itemView
itemView,
userGroups ?: emptyList(),
userCircles ?: emptyList()
)
}
return processedMessageText
@ -105,16 +111,21 @@ class MessageUtils(val context: Context) {
messageParameters: HashMap<String?, HashMap<String?, String?>>,
message: ChatMessage,
messageString: Spanned,
itemView: View?
itemView: View?,
userGroups: List<String>,
userCircles: List<String>
): Spanned {
var messageStringInternal = messageString
for (key in messageParameters.keys) {
val individualHashMap = message.messageParameters?.get(key)
if (individualHashMap != null) {
when (individualHashMap["type"]) {
"user", "guest", "call", "user-group", "email", "circle" -> {
val chip = if (individualHashMap["id"]?.equals(message.activeUser?.userId) == true) {
val chip = if (individualHashMap["id"] == message.activeUser!!.userId ||
userGroups.any { it == individualHashMap["name"] } ||
userCircles.any { it == individualHashMap["name"] } ||
individualHashMap["type"] == "call"
) {
R.xml.chip_you
} else {
R.xml.chip_others