refactor: 重构data层

1.重构data层
2.重构ChatAdapter减少大量重复代码
This commit is contained in:
糕小菜 2024-11-26 13:13:39 +08:00
parent e1816f525a
commit 57b6fd166e
42 changed files with 348 additions and 243 deletions

View File

@ -1,8 +1,8 @@
package com.kaixed.kchat
import android.app.Application
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.ObjectBox.init
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.box.ObjectBox.init
import com.kaixed.kchat.utils.DensityUtil
import com.tencent.mmkv.MMKV
import io.objectbox.android.Admin
@ -18,6 +18,7 @@ class App : Application() {
MMKV.initialize(this)
init(this)
Admin(getBoxStore()).start(this)
DensityUtil.init(this)

View File

@ -1,8 +1,8 @@
package com.kaixed.kchat.data.objectbox.data
package com.kaixed.kchat.data
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.objectbox.entity.Contact_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact_
/**
* @Author: kaixed
@ -14,5 +14,4 @@ object LocalContact {
fun getContactByUsername(contactId: String): Contact? {
return contactBox.query(Contact_.username.equal(contactId)).build().findFirst()
}
}

View File

@ -0,0 +1,26 @@
package com.kaixed.kchat.data.local.box
import android.content.Context
import com.kaixed.kchat.data.local.entity.MyObjectBox
import io.objectbox.Box
import io.objectbox.BoxStore
/**
* @Author: kaixed
* @Date: 2024/10/24 16:57
*/
object ObjectBox {
private lateinit var boxStore: BoxStore
fun init(context: Context) {
boxStore = MyObjectBox.builder()
.androidContext(context)
.build()
}
fun getBoxStore(): BoxStore = boxStore
fun <T> getBox(entityClass: Class<T>): Box<T> {
return boxStore.boxFor(entityClass)
}
}

View File

@ -1,4 +1,4 @@
package com.kaixed.kchat.data.objectbox.entity
package com.kaixed.kchat.data.local.entity
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id

View File

@ -1,4 +1,4 @@
package com.kaixed.kchat.data.objectbox.entity
package com.kaixed.kchat.data.local.entity
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id

View File

@ -1,4 +1,4 @@
package com.kaixed.kchat.data.objectbox.entity
package com.kaixed.kchat.data.local.entity
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id

View File

@ -1,4 +1,4 @@
package com.kaixed.kchat.data.objectbox.entity
package com.kaixed.kchat.data.local.entity
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id

View File

@ -1,21 +0,0 @@
package com.kaixed.kchat.data.objectbox
import android.content.Context
import com.kaixed.kchat.data.objectbox.entity.MyObjectBox
import io.objectbox.BoxStore
/**
* @Author: kaixed
* @Date: 2024/10/24 16:57
*/
object ObjectBox {
private var store: BoxStore? = null
fun init(context: Context) {
store = MyObjectBox.builder()
.androidContext(context)
.build()
}
fun getBoxStore(): BoxStore = checkNotNull(store) { "ObjectBox is not initialized." }
}

View File

@ -1,8 +1,8 @@
package com.kaixed.kchat.repository
package com.kaixed.kchat.data.repository
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.objectbox.entity.Contact_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact_
import com.kaixed.kchat.model.friend.FriendRequestItem
import com.kaixed.kchat.model.search.User
import com.kaixed.kchat.network.ApiCall.apiCall

View File

@ -1,8 +1,8 @@
package com.kaixed.kchat.repository
package com.kaixed.kchat.data.repository
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.objectbox.entity.UserInfo_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.UserInfo
import com.kaixed.kchat.data.local.entity.UserInfo_
import com.kaixed.kchat.model.request.RegisterRequest
import com.kaixed.kchat.model.response.register.Register
import com.kaixed.kchat.network.ApiCall.apiCall

View File

@ -1,8 +1,8 @@
package com.kaixed.kchat.repository
package com.kaixed.kchat.data.repository
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.objectbox.entity.UserInfo_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.UserInfo
import com.kaixed.kchat.data.local.entity.UserInfo_
import com.kaixed.kchat.model.request.UserRequest
import com.kaixed.kchat.model.search.SearchUser
import com.kaixed.kchat.network.RetrofitClient

View File

@ -1,4 +1,4 @@
package com.kaixed.kchat.repository
package com.kaixed.kchat.data.repository
import com.kaixed.kchat.model.response.search.User
import com.kaixed.kchat.network.RetrofitClient

View File

@ -1,6 +1,6 @@
package com.kaixed.kchat.model.friend
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact
import kotlinx.serialization.Serializable
@Serializable

View File

@ -1,6 +1,6 @@
package com.kaixed.kchat.model.response.friend
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact
import kotlinx.serialization.Serializable
/**

View File

@ -1,6 +1,6 @@
package com.kaixed.kchat.model.response.login
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.local.entity.UserInfo
import kotlinx.serialization.Serializable
@Serializable

View File

@ -1,6 +1,6 @@
package com.kaixed.kchat.network.service
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.model.friend.FriendRequestItem
import com.kaixed.kchat.model.search.User
import com.kaixed.kchat.network.ApiResponse

View File

@ -1,17 +1,13 @@
package com.kaixed.kchat.network.service
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.local.entity.UserInfo
import com.kaixed.kchat.model.request.RegisterRequest
import com.kaixed.kchat.model.request.UserRequest
import com.kaixed.kchat.model.response.friend.SearchFriends
import com.kaixed.kchat.model.response.register.Register
import com.kaixed.kchat.model.response.search.User
import com.kaixed.kchat.model.response.user.ChangeNickname
import com.kaixed.kchat.model.response.user.UploadAvatar
import com.kaixed.kchat.model.search.SearchUser
import com.kaixed.kchat.network.ApiResponse
import okhttp3.MultipartBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded

View File

@ -8,10 +8,10 @@ import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.google.gson.Gson
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Conversation
import com.kaixed.kchat.data.objectbox.entity.Conversation_
import com.kaixed.kchat.data.objectbox.entity.Messages
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Conversation
import com.kaixed.kchat.data.local.entity.Conversation_
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.network.NetworkInterface.WEBSOCKET
import com.kaixed.kchat.network.NetworkInterface.WEBSOCKET_SERVER_URL
import com.kaixed.kchat.network.OkhttpHelper

View File

@ -24,9 +24,9 @@ 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.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Messages
import com.kaixed.kchat.data.objectbox.entity.Messages_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.data.local.entity.Messages_
import com.kaixed.kchat.databinding.ActivityChatBinding
import com.kaixed.kchat.model.FunctionItem
import com.kaixed.kchat.service.WebSocketService

View File

@ -4,7 +4,7 @@ import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import com.bumptech.glide.Glide
import com.kaixed.kchat.data.objectbox.data.LocalContact.getContactByUsername
import com.kaixed.kchat.data.LocalContact.getContactByUsername
import com.kaixed.kchat.databinding.ActivityChatDetailBinding
import com.kaixed.kchat.ui.base.BaseActivity

View File

@ -5,9 +5,9 @@ import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.activity.enableEdgeToEdge
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.objectbox.entity.Contact_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact_
import com.kaixed.kchat.databinding.ActivityContactsDetailBinding
import com.kaixed.kchat.ui.base.BaseActivity
import io.objectbox.Box

View File

@ -11,8 +11,8 @@ import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.databinding.ActivityMainBinding
import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.ui.fragment.ContactFragment

View File

@ -13,9 +13,9 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.objectbox.entity.UserInfo_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.UserInfo
import com.kaixed.kchat.data.local.entity.UserInfo_
import com.kaixed.kchat.databinding.ActivityProfileDetailBinding
import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.ui.widget.LoadingDialogFragment

View File

@ -14,8 +14,8 @@ import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.widget.addTextChangedListener
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.UserInfo
import com.kaixed.kchat.databinding.ActivityRegisterBinding
import com.kaixed.kchat.model.request.RegisterRequest
import com.kaixed.kchat.ui.base.BaseActivity

View File

@ -6,8 +6,8 @@ import android.os.Looper
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.core.widget.addTextChangedListener
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.UserInfo
import com.kaixed.kchat.databinding.ActivityRenameBinding
import com.kaixed.kchat.model.request.UserRequest
import com.kaixed.kchat.ui.base.BaseActivity

View File

@ -12,10 +12,9 @@ import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.lifecycleScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.data.LocalContact
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.objectbox.entity.Contact_
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.LocalContact
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.databinding.ActivitySetRemarkAndLabelBinding
import com.kaixed.kchat.ui.base.BaseActivity
import com.kaixed.kchat.ui.widget.LoadingDialogFragment

View File

@ -2,23 +2,20 @@ package com.kaixed.kchat.ui.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.drake.spannable.replaceSpan
import com.drake.spannable.span.CenterImageSpan
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.ObjectBox
import com.kaixed.kchat.data.objectbox.entity.Messages
import com.kaixed.kchat.databinding.ChatRecycleItemCustomMineBinding
import com.kaixed.kchat.databinding.ChatRecycleItemCustomOtherBinding
import com.kaixed.kchat.databinding.ChatRecycleItemImageMineBinding
import com.kaixed.kchat.databinding.ChatRecycleItemImageOtherBinding
import com.kaixed.kchat.data.local.box.ObjectBox
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.utils.ConstantsUtil.getUsername
import com.kaixed.kchat.utils.PopWindowUtil.showPopupWindow
import com.kaixed.kchat.utils.TextUtil
import com.kaixed.kchat.utils.ViewUtil.changeTimerVisibility
import com.kaixed.kchat.utils.ViewUtil.changeView
import io.objectbox.Box
import java.util.LinkedList
@ -28,72 +25,47 @@ class ChatAdapter(
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
// 普通文本消息
private const val ITEM_TYPE_CUSTOM_MINE = 0
private const val ITEM_TYPE_CUSTOM_OTHER = 1
const val CUSTOM = 0
// 提示消息,如撤回消息
private const val ITEM_TYPE_TIP_MINE = 2
private const val ITEM_TYPE_TIP_OTHER = 3
// 提示消息
const val TIP = 2
// 图片消息
private const val ITEM_TYPE_IMAGE_MINE = 4
private const val ITEM_TYPE_IMAGE_OTHER = 5
const val IMAGE = 4
// 语音消息
private const val ITEM_TYPE_VOICE_MINE = 6
private const val ITEM_TYPE_VOICE_OTHER = 7
const val VOICE = 6
// 位置消息
private const val ITEM_TYPE_LOCATION_MINE = 8
private const val ITEM_TYPE_LOCATION_OTHER = 9
const val LOCATION = 8
// 表情消息
private const val ITEM_TYPE_EMOJI_MINE = 10
private const val ITEM_TYPE_EMOJI_OTHER = 11
const val EMOJI = 10
// 红包消息
private const val ITEM_TYPE_RED_PACKET_MINE = 12
private const val ITEM_TYPE_RED_PACKET_OTHER = 13
const val RED_PACKET = 12
private const val TAG = "ChatAdapter"
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
ITEM_TYPE_CUSTOM_MINE -> {
CustomViewMineHolder(
ChatRecycleItemCustomMineBinding.inflate(
CUSTOM -> {
CustomViewHolder(
ChatRecycleItemCustomNormalBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
)
}
ITEM_TYPE_CUSTOM_OTHER -> {
CustomViewOtherHolder(
ChatRecycleItemCustomOtherBinding.inflate(
IMAGE -> {
ImageViewHolder(
ChatRecycleItemImageNormalBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
)
}
ITEM_TYPE_IMAGE_OTHER -> {
ImageViewOtherHolder(
ChatRecycleItemImageOtherBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
)
}
ITEM_TYPE_IMAGE_MINE -> {
ImageViewMineHolder(
ChatRecycleItemImageMineBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
)
}
else -> {
TipViewHolder(
ChatRecycleItemTipBinding.inflate(
@ -108,83 +80,20 @@ class ChatAdapter(
val singleMessage = messages[position]
when (holder) {
is ImageViewOtherHolder -> {
Glide.with(context).load(singleMessage.content).into(holder.binding.image)
if (position == messages.size - 1) {
holder.binding.tvTimer.visibility = View.VISIBLE
holder.binding.tvTimer.text =
TextUtil.getTimestampString(singleMessage.timestamp)
} else {
if (singleMessage.timestamp - messages[position + 1].timestamp < 1L * 60 * 1000) {
holder.binding.tvTimer.visibility = View.GONE
} else {
holder.binding.tvTimer.visibility = View.VISIBLE
holder.binding.tvTimer.text =
TextUtil.getTimestampString(singleMessage.timestamp)
}
}
is CustomViewHolder -> {
holder.bindData(singleMessage)
changeTimerVisibility(position, messages, holder.binding.tvTimer, singleMessage)
}
is ImageViewHolder -> {
holder.bindData(singleMessage)
changeTimerVisibility(position, messages, holder.binding.tvTimer, singleMessage)
}
is TipViewHolder -> {
holder.bindData(singleMessage)
}
is CustomViewMineHolder -> {
if (position == messages.size - 1) {
holder.binding.tvTimer.visibility = View.VISIBLE
holder.binding.tvTimer.text =
TextUtil.getTimestampString(singleMessage.timestamp)
} else {
if (singleMessage.timestamp - messages[position + 1].timestamp < 1L * 60 * 1000) {
holder.binding.tvTimer.visibility = View.GONE
} else {
holder.binding.tvTimer.visibility = View.VISIBLE
holder.binding.tvTimer.text =
TextUtil.getTimestampString(singleMessage.timestamp)
}
}
holder.binding.tvMessageContent.setOnLongClickListener {
showPopupWindow(
context,
holder.binding.tvMessageContent,
singleMessage.senderId == getUsername()
)
true
}
holder.binding.tvMessageContent.text = singleMessage.content.replaceSpan("[委屈]") {
CenterImageSpan(context, R.drawable.emoji).setDrawableSize(55)
}
}
is CustomViewOtherHolder -> {
if (position == messages.size - 1) {
holder.binding.tvTimer.visibility = View.VISIBLE
holder.binding.tvTimer.text =
TextUtil.getTimestampString(singleMessage.timestamp)
} else {
if (singleMessage.timestamp - messages[position + 1].timestamp < 1L * 60 * 1000) {
holder.binding.tvTimer.visibility = View.GONE
} else {
holder.binding.tvTimer.visibility = View.VISIBLE
holder.binding.tvTimer.text =
TextUtil.getTimestampString(singleMessage.timestamp)
}
}
holder.binding.tvMessageContent.setOnLongClickListener {
showPopupWindow(
context,
holder.binding.tvMessageContent,
singleMessage.senderId == getUsername()
)
true
}
holder.binding.tvMessageContent.text = singleMessage.content.replaceSpan("[委屈]") {
CenterImageSpan(context, R.drawable.emoji).setDrawableSize(55)
}
}
}
}
@ -199,25 +108,42 @@ class ChatAdapter(
}
}
class CustomViewMineHolder(val binding: ChatRecycleItemCustomMineBinding) :
RecyclerView.ViewHolder(binding.root)
class CustomViewOtherHolder(val binding: ChatRecycleItemCustomOtherBinding) :
RecyclerView.ViewHolder(binding.root)
class CustomViewHolder(val binding: ChatRecycleItemCustomNormalBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bindData(message: Messages) {
val sender = message.senderId == getUsername()
binding.tvMessageContent.text = message.content.replaceSpan("[委屈]") {
CenterImageSpan(binding.root.context, R.drawable.emoji).setDrawableSize(55)
}
class ImageViewMineHolder(val binding: ChatRecycleItemImageMineBinding) :
RecyclerView.ViewHolder(binding.root)
changeView(
parentView = binding.root,
sender = sender,
avatarId = binding.ifvAvatar.id,
contentId = binding.tvMessageContent.id
)
}
}
class ImageViewOtherHolder(val binding: ChatRecycleItemImageOtherBinding) :
RecyclerView.ViewHolder(binding.root)
class ImageViewHolder(val binding: ChatRecycleItemImageNormalBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bindData(message: Messages) {
Glide.with(binding.root.context).load(message.content).into(binding.image)
val sender = message.senderId == getUsername()
changeView(
parentView = binding.root,
sender = sender,
avatarId = binding.ifvAvatar.id,
contentId = binding.image.id
)
}
}
override fun getItemViewType(position: Int): Int {
val message = messages[position]
return if (message.senderId == getUsername()) {
message.type.toInt()
} else {
message.type.toInt() + 1
}
return messages[position].type.toInt()
}
private fun updateDb(message: Messages) {
@ -226,5 +152,4 @@ class ChatAdapter(
}
override fun getItemCount(): Int = messages.size
}

View File

@ -13,7 +13,7 @@ import com.bumptech.glide.request.RequestOptions
import com.drake.spannable.replaceSpan
import com.drake.spannable.span.CenterImageSpan
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.entity.Conversation
import com.kaixed.kchat.data.local.entity.Conversation
import com.kaixed.kchat.databinding.ChatMainItemBinding
import com.kaixed.kchat.ui.activity.ChatActivity
import com.kaixed.kchat.ui.i.OnChatListItemClickListener

View File

@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.databinding.FriendRecycleFooterItemBinding
import com.kaixed.kchat.databinding.FriendRecycleItemBinding
import com.kaixed.kchat.ui.activity.ContactRequestListActivity

View File

@ -11,7 +11,7 @@ import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.databinding.FragmentContactBinding
import com.kaixed.kchat.ui.adapter.FriendListAdapter
import com.kaixed.kchat.ui.base.BaseFragment

View File

@ -20,10 +20,10 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity.BIND_AUTO_CREATE
import androidx.recyclerview.widget.LinearLayoutManager
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Conversation
import com.kaixed.kchat.data.objectbox.entity.Conversation_
import com.kaixed.kchat.data.objectbox.entity.Messages
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Conversation
import com.kaixed.kchat.data.local.entity.Conversation_
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.databinding.FragmentHomeBinding
import com.kaixed.kchat.model.HomeItem
import com.kaixed.kchat.service.WebSocketService

View File

@ -8,9 +8,9 @@ import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.kaixed.kchat.R
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Conversation
import com.kaixed.kchat.data.objectbox.entity.Messages
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Conversation
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.databinding.BottomSheetLayoutBinding
import com.kaixed.kchat.ui.activity.LoginActivity
import com.kaixed.kchat.utils.Constants.MMKV_USER_SESSION

View File

@ -1,6 +1,7 @@
package com.kaixed.kchat.utils
import android.content.Context
import android.util.TypedValue
/**
* @Author: kaixed
@ -15,7 +16,18 @@ object DensityUtil {
}
fun dpToPx(dp: Int): Int =
(appContext.resources.displayMetrics.density * dp).toInt()
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
appContext.resources.displayMetrics
).toInt()
fun dp2Px(dp: Int): Int =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
appContext.resources.displayMetrics
).toInt()
fun pxToDp(px: Int): Int =
(px / appContext.resources.displayMetrics.density).toInt()

View File

@ -22,7 +22,7 @@ object TextUtil {
// 判断是否是昨天
if (isYesterday(timestamp)) {
return "昨天${formatTimestamp(timestamp, "HH:mm")}"
return "昨天 ${formatTimestamp(timestamp, "HH:mm")}"
}
// 判断是否超过两天

View File

@ -0,0 +1,68 @@
package com.kaixed.kchat.utils
import android.view.View
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import com.kaixed.kchat.data.local.entity.Messages
import com.kaixed.kchat.utils.DensityUtil.dp2Px
/**
* @Author: kaixed
* @Date: 2024/11/26 12:12
*/
object ViewUtil {
fun changeView(
parentView: ConstraintLayout,
sender: Boolean,
avatarId: Int,
contentId: Int
) {
ConstraintSet().apply {
clone(parentView)
if (sender) {
connect(
avatarId, ConstraintSet.END,
parentView.id, ConstraintSet.END,
dp2Px(10)
)
connect(
contentId, ConstraintSet.END,
avatarId, ConstraintSet.START,
dp2Px(10)
)
} else {
connect(
avatarId, ConstraintSet.START,
parentView.id, ConstraintSet.START,
dp2Px(10)
)
connect(
contentId, ConstraintSet.START,
avatarId, ConstraintSet.END,
dp2Px(10)
)
}
applyTo(parentView)
}
}
fun changeTimerVisibility(
position: Int,
messages: List<Messages>,
tvTimer: TextView,
singleMessage: Messages
) {
val showTimer =
if (position == messages.size - 1) true else
singleMessage.timestamp - messages[position + 1].timestamp >= 1L * 60 * 1000
if (showTimer) {
tvTimer.visibility = View.VISIBLE
tvTimer.text = TextUtil.getTimestampString(singleMessage.timestamp)
} else {
tvTimer.visibility = View.GONE
}
tvTimer.visibility = if (showTimer) View.VISIBLE else View.GONE
tvTimer.text = TextUtil.getTimestampString(singleMessage.timestamp)
}
}

View File

@ -1,7 +1,7 @@
package com.kaixed.kchat.utils.handle
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.box.ObjectBox.getBoxStore
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.utils.Pinyin4jUtil
import io.objectbox.Box

View File

@ -4,11 +4,11 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.kaixed.kchat.data.objectbox.ObjectBox.getBoxStore
import com.kaixed.kchat.data.objectbox.entity.Contact
import com.kaixed.kchat.data.local.box.ObjectBox.getBox
import com.kaixed.kchat.data.local.entity.Contact
import com.kaixed.kchat.model.friend.FriendRequestItem
import com.kaixed.kchat.model.search.User
import com.kaixed.kchat.repository.ContactRepository
import com.kaixed.kchat.data.repository.ContactRepository
import io.objectbox.Box
import kotlinx.coroutines.launch
@ -95,7 +95,7 @@ class ContactViewModel : ViewModel() {
}
fun loadFriendListInDb(): List<Contact> {
val contactBox: Box<Contact> = getBoxStore().boxFor(Contact::class.java)
val contactBox: Box<Contact> = getBox(Contact::class.java)
val sortedContacts = contactBox.query()
.sort { contact1, contact2 ->

View File

@ -4,15 +4,15 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.kaixed.kchat.data.objectbox.entity.UserInfo
import com.kaixed.kchat.data.local.entity.UserInfo
import com.kaixed.kchat.model.request.RegisterRequest
import com.kaixed.kchat.model.request.UserRequest
import com.kaixed.kchat.model.response.register.Register
import com.kaixed.kchat.model.response.search.User
import com.kaixed.kchat.model.search.SearchUser
import com.kaixed.kchat.repository.UserAuthRepository
import com.kaixed.kchat.repository.UserProfileRepository
import com.kaixed.kchat.repository.UserSearchRepository
import com.kaixed.kchat.data.repository.UserAuthRepository
import com.kaixed.kchat.data.repository.UserProfileRepository
import com.kaixed.kchat.data.repository.UserSearchRepository
import kotlinx.coroutines.launch
import okhttp3.MultipartBody

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp">
<TextView
android:id="@+id/tv_timer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="20dp"
android:text="昨天"
android:textSize="12sp"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/ifv_avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginVertical="20dp"
android:src="@drawable/ic_avatar"
app:layout_constraintTop_toBottomOf="@id/tv_timer"
app:roundPercent="0.3" />
<TextView
android:id="@+id/tv_message_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/chat_send_btn_bac_mine"
android:gravity="center_vertical"
android:maxWidth="250dp"
android:minHeight="35dp"
android:paddingHorizontal="12dp"
android:paddingVertical="6dp"
android:text="haha"
android:textColor="@color/white"
android:textColorHighlight="#CCCCCC"
android:textIsSelectable="true"
android:textSize="17sp"
app:layout_constraintTop_toTopOf="@id/ifv_avatar" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -6,14 +6,33 @@
android:paddingVertical="10dp">
<TextView
android:layout_width="wrap_content"
android:id="@+id/tv_timer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="这是一个小tip"
android:textColor="@color/black"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:gravity="center_horizontal"
android:paddingTop="20dp"
android:text="昨天"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/ifv_avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginVertical="20dp"
android:layout_marginEnd="10dp"
android:src="@drawable/ic_avatar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_timer"
app:roundPercent="0.3" />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginEnd="10dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toStartOf="@id/ifv_avatar"
app:layout_constraintTop_toTopOf="@id/ifv_avatar"
app:roundPercent="0.2" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp">
<TextView
android:id="@+id/tv_timer"
android:layout_width="match_parent"
android:textSize="12sp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="20dp"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/ifv_avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginVertical="20dp"
android:src="@drawable/ic_avatar"
app:layout_constraintTop_toBottomOf="@id/tv_timer"
app:roundPercent="0.3" />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
app:layout_constraintTop_toTopOf="@id/ifv_avatar"
app:roundPercent="0.15" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -25,13 +25,14 @@
app:layout_constraintTop_toBottomOf="@id/tv_timer"
app:roundPercent="0.3" />
<ImageView
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginStart="10dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toEndOf="@id/ifv_avatar"
app:layout_constraintTop_toTopOf="@id/ifv_avatar" />
app:layout_constraintTop_toTopOf="@id/ifv_avatar"
app:roundPercent="0.2" />
</androidx.constraintlayout.widget.ConstraintLayout>