diff --git a/.idea/GitCommitMessageStorage.xml b/.idea/GitCommitMessageStorage.xml
index 3b56900..e4fd56a 100644
--- a/.idea/GitCommitMessageStorage.xml
+++ b/.idea/GitCommitMessageStorage.xml
@@ -2,19 +2,7 @@
\ No newline at end of file
diff --git a/app/src/main/java/com/kaixed/kchat/manager/ConversationManager.kt b/app/src/main/java/com/kaixed/kchat/manager/ConversationManager.kt
index c66deb3..5aa69c4 100644
--- a/app/src/main/java/com/kaixed/kchat/manager/ConversationManager.kt
+++ b/app/src/main/java/com/kaixed/kchat/manager/ConversationManager.kt
@@ -30,6 +30,7 @@ object ConversationManager {
private val conversationMap: MutableMap = mutableMapOf()
private var unreadCount = 0
+ val unReadMsgCount get() = unreadCount
init {
loadConversations()
@@ -49,7 +50,8 @@ object ConversationManager {
}
fun handleMessages(messages: Messages) {
- if (messages.senderId != getUsername() || messages.talkerId != getCurrentContactId()) {
+ val talkerId = getCurrentContactId()
+ if (messages.senderId != getUsername() && messages.talkerId != talkerId) {
unreadCount++
}
val updatedConversation = updateConversation(messages)
diff --git a/app/src/main/java/com/kaixed/kchat/manager/MessagesManager.kt b/app/src/main/java/com/kaixed/kchat/manager/MessagesManager.kt
index c9d167a..a3679ac 100644
--- a/app/src/main/java/com/kaixed/kchat/manager/MessagesManager.kt
+++ b/app/src/main/java/com/kaixed/kchat/manager/MessagesManager.kt
@@ -1,5 +1,6 @@
package com.kaixed.kchat.manager
+import com.kaixed.kchat.data.DataBase
import com.kaixed.kchat.data.LocalDatabase
import com.kaixed.kchat.data.LocalDatabase.getAllHistoryMessages
import com.kaixed.kchat.data.LocalDatabase.getMessagesWithContact
@@ -25,6 +26,14 @@ object MessagesManager {
private var loading = false
private var tempIndex: Long = 0
+ fun deleteMessage(msgLocalId: Long) {
+ DataBase.messagesBox.remove(msgLocalId)
+ val msg = _messages.value.toMutableList().apply {
+ removeIf { it.msgLocalId == msgLocalId }
+ }
+ _messages.value = msg
+ }
+
fun queryHistory(msgLocalId: Long): Int {
_messages.value = emptyList()
val msg = getAllHistoryMessages(contactId, msgLocalId)
@@ -49,6 +58,7 @@ object MessagesManager {
}
fun receiveMessage(messages: Messages) {
+ if (messages.talkerId != contactId) return
if (_messages.value.first() == messages) return
_messages.value = _messages.value.toMutableList().apply {
add(0, messages)
diff --git a/app/src/main/java/com/kaixed/kchat/network/ApiCall.kt b/app/src/main/java/com/kaixed/kchat/network/ApiCall.kt
index 54dcc97..cfc28d0 100644
--- a/app/src/main/java/com/kaixed/kchat/network/ApiCall.kt
+++ b/app/src/main/java/com/kaixed/kchat/network/ApiCall.kt
@@ -6,8 +6,7 @@ package com.kaixed.kchat.network
*/
object ApiCall {
suspend fun apiCall(
- apiCall: suspend () -> ApiResponse,
- errorMessage: String = "操作失败"
+ apiCall: suspend () -> ApiResponse, errorMessage: String = "操作失败"
): Result {
return try {
val response = apiCall()
diff --git a/app/src/main/java/com/kaixed/kchat/ui/activity/ChatActivity.kt b/app/src/main/java/com/kaixed/kchat/ui/activity/ChatActivity.kt
index 75dfa6b..5314674 100644
--- a/app/src/main/java/com/kaixed/kchat/ui/activity/ChatActivity.kt
+++ b/app/src/main/java/com/kaixed/kchat/ui/activity/ChatActivity.kt
@@ -28,10 +28,12 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.kaixed.kchat.R
+import com.kaixed.kchat.data.event.UnreadEvent
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.data.model.FunctionItem
import com.kaixed.kchat.databinding.ActivityChatBinding
+import com.kaixed.kchat.manager.ConversationManager
import com.kaixed.kchat.manager.MessagesManager
import com.kaixed.kchat.processor.MessageProcessor
import com.kaixed.kchat.service.WebSocketService
@@ -59,6 +61,9 @@ import com.tencent.mmkv.MMKV
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import kotlinx.coroutines.launch
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject
import java.io.File
@@ -108,6 +113,7 @@ class ChatActivity : BaseActivity(), OnItemClickListener,
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
+ EventBus.getDefault().register(this)
firstLoadData()
initView()
setListener()
@@ -367,6 +373,7 @@ class ChatActivity : BaseActivity(), OnItemClickListener,
}
private fun initView() {
+ binding.ctb.setUnReadCount(ConversationManager.unReadMsgCount)
setupFunctionPanel()
setRecycleView()
contactNickname?.let {
@@ -461,8 +468,15 @@ class ChatActivity : BaseActivity(), OnItemClickListener,
)
}
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ fun onMessageEvent(unreadEvent: UnreadEvent) {
+ val unreadCount = unreadEvent.unreadCount
+ binding.ctb.setUnReadCount(unreadCount)
+ }
+
override fun onDestroy() {
super.onDestroy()
+ EventBus.getDefault().unregister(this)
MessagesManager.resetMessages()
mmkv.putString(CURRENT_CONTACT_ID, "")
if (bound) {
diff --git a/app/src/main/java/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt b/app/src/main/java/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt
index 4637f49..a7f9bfb 100644
--- a/app/src/main/java/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt
+++ b/app/src/main/java/com/kaixed/kchat/ui/activity/setting/UpdatePasswordActivity.kt
@@ -54,9 +54,7 @@ class UpdatePasswordActivity : BaseActivity() {
} else {
loadingDialog.showLoading(supportFragmentManager)
val updatePassword = UpdatePasswordRequest(
- ConstantsUtil.getUsername(),
- oldPassword,
- newPassword
+ ConstantsUtil.getUsername(), oldPassword, newPassword
)
userViewModel.updatePassword(updatePassword)
}
@@ -93,9 +91,8 @@ class UpdatePasswordActivity : BaseActivity() {
}
override fun afterTextChanged(s: Editable?) {
- val enable = binding.cetNewPassword.text?.length != 0 &&
- binding.cetOldPassword.text?.length != 0 &&
- binding.cetConfirmPassword.text?.length != 0
+ val enable =
+ binding.cetNewPassword.text?.length != 0 && binding.cetOldPassword.text?.length != 0 && binding.cetConfirmPassword.text?.length != 0
binding.titleBar.setBtnEnable(enable)
}
}
diff --git a/app/src/main/java/com/kaixed/kchat/ui/adapter/ChatAdapter.kt b/app/src/main/java/com/kaixed/kchat/ui/adapter/ChatAdapter.kt
index 9103fdc..f82a4a3 100644
--- a/app/src/main/java/com/kaixed/kchat/ui/adapter/ChatAdapter.kt
+++ b/app/src/main/java/com/kaixed/kchat/ui/adapter/ChatAdapter.kt
@@ -1,7 +1,6 @@
package com.kaixed.kchat.ui.adapter
import android.content.Context
-import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
@@ -19,10 +18,10 @@ import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.databinding.ChatRecycleItemCustomNormalBinding
import com.kaixed.kchat.databinding.ChatRecycleItemImageNormalBinding
import com.kaixed.kchat.databinding.ChatRecycleItemTipBinding
+import com.kaixed.kchat.manager.MessagesManager
import com.kaixed.kchat.utils.ConstantsUtil
import com.kaixed.kchat.utils.ConstantsUtil.getUsername
import com.kaixed.kchat.utils.PopWindowUtil.showPopupWindow
-import com.kaixed.kchat.utils.TextUtil
import com.kaixed.kchat.utils.TextUtil.extractDimensionsAndPrefix
import com.kaixed.kchat.utils.ViewUtil.changeTimerVisibility
import com.kaixed.kchat.utils.ViewUtil.setViewVisibility
@@ -57,22 +56,25 @@ class ChatAdapter(
return when (viewType) {
CUSTOM -> {
CustomViewHolder(
- ChatRecycleItemCustomNormalBinding
- .inflate(LayoutInflater.from(parent.context), parent, false)
+ ChatRecycleItemCustomNormalBinding.inflate(
+ LayoutInflater.from(parent.context), parent, false
+ )
)
}
IMAGE -> {
ImageViewHolder(
- ChatRecycleItemImageNormalBinding
- .inflate(LayoutInflater.from(parent.context), parent, false)
+ ChatRecycleItemImageNormalBinding.inflate(
+ LayoutInflater.from(parent.context), parent, false
+ )
)
}
else -> {
TipViewHolder(
- ChatRecycleItemTipBinding
- .inflate(LayoutInflater.from(parent.context), parent, false)
+ ChatRecycleItemTipBinding.inflate(
+ LayoutInflater.from(parent.context), parent, false
+ )
)
}
}
@@ -108,30 +110,18 @@ class ChatAdapter(
}
contentView?.setOnLongClickListener {
- Log.d("haha", "长按了:${message.content} position: $position")
val popupWindow = showPopupWindow(context, it, message.senderId == getUsername())
val deleteButton = popupWindow.contentView.findViewById(R.id.tv_delete)
deleteButton.setOnClickListener {
- deleteMessage(position, message)
- Log.d("haha", "长按并删除了了:${message.content} position: $position")
+ deleteMessage(message)
popupWindow.dismiss()
}
true
}
}
- private fun deleteMessage(position: Int, message: Messages) {
- // 从数据库删除
-// val messagesBox: Box = getBox(Messages::class.java)
-// messagesBox.remove(message.msgLocalId)
-//
-// // 更新数据源并通知 RecyclerView
-// messages.removeAt(position)
-// notifyItemRemoved(position)
-//
-// if (position != messages.size) { // 如果移除的是最后一个,忽略
-// notifyItemRangeChanged(position, messages.size - position);
-// }
+ private fun deleteMessage(message: Messages) {
+ MessagesManager.deleteMessage(message.msgLocalId)
}
interface HasTimer {
@@ -162,8 +152,7 @@ class ChatAdapter(
contentId = binding.tvMsgContent.id,
contentMineId = binding.tvMsgContentMine.id
)
- val avatarUrl =
- if (sender) ConstantsUtil.getAvatarUrl() else message.avatarUrl
+ val avatarUrl = if (sender) ConstantsUtil.getAvatarUrl() else message.avatarUrl
Glide.with(binding.root.context).load(avatarUrl)
.into(if (sender) binding.ifvAvatarMine else binding.ifvAvatar)
@@ -182,8 +171,7 @@ class ChatAdapter(
RecyclerView.ViewHolder(binding.root), HasTimer {
fun bindData(message: Messages) {
val sender = message.senderId == getUsername()
- val avatarUrl =
- if (sender) ConstantsUtil.getAvatarUrl() else message.avatarUrl
+ val avatarUrl = if (sender) ConstantsUtil.getAvatarUrl() else message.avatarUrl
Glide.with(binding.root.context).load(avatarUrl)
.into(if (sender) binding.ifvAvatarMine else binding.ifvAvatar)
@@ -209,8 +197,8 @@ class ChatAdapter(
this.width = width
}
}
- Glide.with(binding.root.context).load(url)
- .placeholder(R.drawable.image_loading).into(imageView)
+ Glide.with(binding.root.context).load(url).placeholder(R.drawable.image_loading)
+ .into(imageView)
} ?: run {
Glide.with(binding.root.context).load(message.content)
.placeholder(R.drawable.image_loading).into(imageView)
diff --git a/app/src/main/java/com/kaixed/kchat/ui/widget/CustomTitleBar.kt b/app/src/main/java/com/kaixed/kchat/ui/widget/CustomTitleBar.kt
index 12649e9..76538ed 100644
--- a/app/src/main/java/com/kaixed/kchat/ui/widget/CustomTitleBar.kt
+++ b/app/src/main/java/com/kaixed/kchat/ui/widget/CustomTitleBar.kt
@@ -67,8 +67,9 @@ class CustomTitleBar @JvmOverloads constructor(
}
}
- fun setOnBackClickListener(listener: OnClickListener?) {
- binding.ivBack.setOnClickListener(listener)
+ fun setUnReadCount(count: Int) {
+ binding.rlUnreadCount.visibility = if (count > 0) View.VISIBLE else View.INVISIBLE
+ binding.tvUnreadCount.text = count.toString()
}
fun setOnSettingClickListener(listener: OnClickListener?) {
diff --git a/app/src/main/java/com/kaixed/kchat/viewmodel/UserViewModel.kt b/app/src/main/java/com/kaixed/kchat/viewmodel/UserViewModel.kt
index 08c18c5..b714db1 100644
--- a/app/src/main/java/com/kaixed/kchat/viewmodel/UserViewModel.kt
+++ b/app/src/main/java/com/kaixed/kchat/viewmodel/UserViewModel.kt
@@ -36,6 +36,7 @@ class UserViewModel : ViewModel() {
viewModelScope.launch {
val result = userProfileRepo.updatePassword(updatePasswordRequest)
_updatePasswordResult.postValue(result)
+ _updatePasswordResult.value = result
}
}
diff --git a/app/src/main/res/drawable/icon_gray_dot.xml b/app/src/main/res/drawable/icon_gray_dot.xml
new file mode 100644
index 0000000..37cf55a
--- /dev/null
+++ b/app/src/main/res/drawable/icon_gray_dot.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/view_title_bar.xml b/app/src/main/res/layout/view_title_bar.xml
index f1846be..ff83ae8 100644
--- a/app/src/main/res/layout/view_title_bar.xml
+++ b/app/src/main/res/layout/view_title_bar.xml
@@ -14,6 +14,29 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
+
+
+
+
+
+