发送文件,图片,视频,处理失败
@ -5,10 +5,12 @@ import android.view.ViewGroup
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyAudioBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyFileBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyImgBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyVideoBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherAudioBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherFileBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherImgBinding
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherVideoBinding
|
||||
import com.tenlionsoft.aimz_k.model.MsgBean
|
||||
@ -16,67 +18,90 @@ import com.tenlionsoft.aimz_k.model.MsgTypeStateEnum
|
||||
import com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel
|
||||
import com.tenlionsoft.baselib.base.BaseBindingAdapter
|
||||
|
||||
class ChatMsgAdapter(datas: List<MsgBean>, viewModel: ChatPageViewModel) :
|
||||
class ChatMsgAdapter(datas: List<MsgBean>, val viewModel: ChatPageViewModel) :
|
||||
BaseBindingAdapter<MsgBean, ViewDataBinding>(datas) {
|
||||
|
||||
override fun getItemBinding(parent: ViewGroup, viewType: Int): ViewDataBinding {
|
||||
when (viewType) {
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_TXT -> {
|
||||
//发送文本
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_TXT ->
|
||||
return ItemMsgOtherBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//发送文本
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_TXT -> {
|
||||
|
||||
//收到文本信息
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_TXT ->
|
||||
return ItemMsgMyBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//收到文本信息
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_MOVIE -> {
|
||||
return ItemMsgMyVideoBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//发送视频
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_MOVIE -> {
|
||||
|
||||
//发送视频
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_MOVIE ->
|
||||
return ItemMsgOtherVideoBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//收到视频
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_IMG -> {
|
||||
return ItemMsgMyImgBinding.inflate(
|
||||
|
||||
//收到视频
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_MOVIE ->
|
||||
return ItemMsgMyVideoBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//发送图片
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_IMG -> {
|
||||
|
||||
//发送图片
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_IMG ->
|
||||
return ItemMsgOtherImgBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//收到图片
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_VOICE -> {
|
||||
|
||||
//收到图片
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_IMG ->
|
||||
return ItemMsgMyImgBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
|
||||
//语音
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_VOICE ->
|
||||
return ItemMsgMyAudioBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//语音
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_VOICE -> {
|
||||
//语音
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_VOICE ->
|
||||
return ItemMsgOtherAudioBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}//语音
|
||||
//发送文件
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_FILE ->
|
||||
return ItemMsgOtherFileBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
|
||||
//收到文件
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_FILE -> {
|
||||
return ItemMsgMyFileBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw IllegalArgumentException("Invalid view type")
|
||||
}
|
||||
@ -89,6 +114,9 @@ class ChatMsgAdapter(datas: List<MsgBean>, viewModel: ChatPageViewModel) :
|
||||
|
||||
override fun bindItem(holder: BaseViewHolder<ViewDataBinding>, position: Int) {
|
||||
val itemType = getItemViewType(position)
|
||||
holder.binding.root.setOnClickListener {
|
||||
viewModel.onItemClickListener?.onItemClick(list[position])
|
||||
}
|
||||
when (itemType) {
|
||||
//发送文本
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_TXT -> {
|
||||
@ -104,28 +132,28 @@ class ChatMsgAdapter(datas: List<MsgBean>, viewModel: ChatPageViewModel) :
|
||||
}
|
||||
//发送视频
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_MOVIE -> {
|
||||
(holder.binding as ItemMsgMyVideoBinding).pos = position
|
||||
(holder.binding as ItemMsgMyVideoBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgMyVideoBinding).state = list[position].status
|
||||
}
|
||||
//收到视频
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_MOVIE -> {
|
||||
(holder.binding as ItemMsgOtherVideoBinding).pos = position
|
||||
(holder.binding as ItemMsgOtherVideoBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgOtherVideoBinding).state = list[position].status
|
||||
}
|
||||
//收到视频
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_MOVIE -> {
|
||||
(holder.binding as ItemMsgMyVideoBinding).pos = position
|
||||
(holder.binding as ItemMsgMyVideoBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgMyVideoBinding).state = list[position].status
|
||||
}
|
||||
//发送图片
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_IMG -> {
|
||||
(holder.binding as ItemMsgMyImgBinding).pos = position
|
||||
(holder.binding as ItemMsgMyImgBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgMyImgBinding).state = list[position].status
|
||||
}
|
||||
//收到图片
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_IMG -> {
|
||||
(holder.binding as ItemMsgOtherImgBinding).pos = position
|
||||
(holder.binding as ItemMsgOtherImgBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgOtherImgBinding).state = list[position].status
|
||||
}
|
||||
//收到图片
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_IMG -> {
|
||||
(holder.binding as ItemMsgMyImgBinding).pos = position
|
||||
(holder.binding as ItemMsgMyImgBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgMyImgBinding).state = list[position].status
|
||||
}
|
||||
//发送语音
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_VOICE -> {
|
||||
(holder.binding as ItemMsgMyAudioBinding).pos = position
|
||||
@ -138,6 +166,18 @@ class ChatMsgAdapter(datas: List<MsgBean>, viewModel: ChatPageViewModel) :
|
||||
(holder.binding as ItemMsgOtherAudioBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgOtherAudioBinding).state = list[position].status
|
||||
}
|
||||
//发送文件
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_FILE -> {
|
||||
(holder.binding as ItemMsgOtherFileBinding).pos = position
|
||||
(holder.binding as ItemMsgOtherFileBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgOtherFileBinding).state = list[position].status
|
||||
}
|
||||
//收到文件
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_FILE -> {
|
||||
(holder.binding as ItemMsgMyFileBinding).pos = position
|
||||
(holder.binding as ItemMsgMyFileBinding).bean = list[position]
|
||||
(holder.binding as ItemMsgMyFileBinding).state = list[position].status
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw IllegalArgumentException("Invalid view type")
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.tenlionsoft.aimz_k.model
|
||||
|
||||
data class FileUploadStateBean(var code: Int, var data: FileDataBean)
|
||||
|
||||
//"fileId": "2b9dfe0b-ef6f-466c-84f6-8aedb7c97d8f",
|
||||
//"fileName": "Screenshot_20230626_092232.jpg",
|
||||
//"fileSize": 103874,
|
||||
//"fileUrl": "api/file/download/2b9dfe0b-ef6f-466c-84f6-8aedb7c97d8f"
|
||||
data class FileDataBean(
|
||||
var fileId: String?,
|
||||
var fileName: String?,
|
||||
var fileSize: Long?,
|
||||
var fileUrl: String
|
||||
)
|
@ -1,6 +1,7 @@
|
||||
package com.tenlionsoft.aimz_k.net
|
||||
|
||||
import com.tenlionsoft.aimz_k.model.BaseSuccessBean
|
||||
import com.tenlionsoft.aimz_k.model.FileUploadStateBean
|
||||
import com.tenlionsoft.baselib.model.VersionBean
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
@ -23,6 +24,7 @@ interface UserApi {
|
||||
@Headers("Content-Type: application/json", "Accept: application/json", "projectName:usercenter")
|
||||
@POST("api/jwt/login")
|
||||
suspend fun doLogin(@Body user: RequestBody): BaseSuccessBean
|
||||
|
||||
/**
|
||||
* 登陆Socket系统
|
||||
* http://192.168.0.26:8888/system/api/anonymous/login
|
||||
@ -43,7 +45,7 @@ interface UserApi {
|
||||
|
||||
|
||||
/**
|
||||
* 上传图片文件
|
||||
* 上传图片
|
||||
* image
|
||||
*
|
||||
* @param file
|
||||
@ -52,8 +54,8 @@ interface UserApi {
|
||||
*/
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("app/file/uploadimage")
|
||||
suspend fun doUploadImage(@Part file: MultipartBody.Part): BaseSuccessBean
|
||||
@POST("api/file/upload/image")
|
||||
suspend fun doUploadImage(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
|
||||
|
||||
/**
|
||||
@ -66,6 +68,22 @@ interface UserApi {
|
||||
*/
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("app/file/uploadvideo")
|
||||
fun doUploadVideo(@Part file: MultipartBody.Part): BaseSuccessBean
|
||||
@POST("api/file/upload/video")
|
||||
suspend fun doUploadVideo(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("api/file/upload/file")
|
||||
suspend fun doUploadFile(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
|
||||
/**
|
||||
* 上传音频
|
||||
*/
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("api/file/upload/audio")
|
||||
suspend fun doUploadAudio(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
}
|
@ -16,11 +16,15 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.atwa.filepicker.core.FilePicker
|
||||
import com.tenlionsoft.aimz_k.R
|
||||
import com.tenlionsoft.aimz_k.databinding.ActivityChatBinding
|
||||
import com.tenlionsoft.aimz_k.model.MsgBean
|
||||
import com.tenlionsoft.aimz_k.model.PickerType
|
||||
import com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel
|
||||
import com.tenlionsoft.baselib.base.BaseActivity
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.utils.DensityUtils
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||
import com.tenlionsoft.baselib.widget.SoftKeyBoardListener
|
||||
import com.tenlionsoft.baselib.widget.wheel.WheelView
|
||||
|
||||
@ -28,13 +32,14 @@ import com.tenlionsoft.baselib.widget.wheel.WheelView
|
||||
/**
|
||||
* 聊天页面
|
||||
*/
|
||||
class ChatActivity : BaseActivity() {
|
||||
class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
private lateinit var mBinding: ActivityChatBinding
|
||||
private lateinit var mLocalReceiver: LocalReceiver
|
||||
var chatPageViewModel: ChatPageViewModel? = null
|
||||
private val filePicker = FilePicker.getInstance(this)
|
||||
private var mContentHeight: Int = 0
|
||||
|
||||
private var mLoading: LoadingDialog? = null;
|
||||
private var bottomHeight = -1
|
||||
override fun bindView() {
|
||||
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_chat);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||
@ -43,9 +48,7 @@ class ChatActivity : BaseActivity() {
|
||||
|
||||
val fromId = intent.getStringExtra("fromId") //传递过来的接收人
|
||||
val name = intent.getStringExtra("name")
|
||||
if (name.isNullOrEmpty()) {
|
||||
mBinding.tvTitle.text = "临时客户"
|
||||
}
|
||||
mBinding.tvTitle.text = if (name.isNullOrEmpty()) "临时客户" else name
|
||||
|
||||
chatPageViewModel = ViewModelProvider(this, object : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
@ -54,7 +57,7 @@ class ChatActivity : BaseActivity() {
|
||||
) as T
|
||||
}
|
||||
})[ChatPageViewModel::class.java]
|
||||
|
||||
chatPageViewModel!!.onItemClickListener = this
|
||||
mBinding.ivBack.setOnClickListener { finish(); }
|
||||
mBinding.viewModel = chatPageViewModel
|
||||
mBinding.lifecycleOwner = this
|
||||
@ -63,27 +66,57 @@ class ChatActivity : BaseActivity() {
|
||||
mBinding.etMsg.append(it.emoji)
|
||||
}
|
||||
|
||||
//显示/隐藏软键盘
|
||||
// chatPageViewModel!!.showSoftKeyboard.observe(this) {
|
||||
// if (it) {
|
||||
// showSoftKeyBoard(mBinding.etMsg)
|
||||
// chatPageViewModel!!.showChooseLayout.value = false
|
||||
// chatPageViewModel!!.showEmojiLayout.value = false
|
||||
// chatPageViewModel!!.showReplyLayout.value = false
|
||||
// val layoutManager = mBinding.rlvChats.layoutManager as LinearLayoutManager
|
||||
// val itemCount = layoutManager.itemCount
|
||||
// mBinding.rlvChats.smoothScrollToPosition(itemCount - 1)
|
||||
// } else {
|
||||
// hideSoftKeyboard()
|
||||
// }
|
||||
// }
|
||||
// mBinding.rlContent.setOnClickListener {
|
||||
// Log.e("ChatActivity", "bindView: 点击")
|
||||
// chatPageViewModel!!.showChooseLayout.value = false
|
||||
// chatPageViewModel!!.showEmojiLayout.value = false
|
||||
// chatPageViewModel!!.showReplyLayout.value = false
|
||||
// hideSoftKeyboard()
|
||||
// }
|
||||
chatPageViewModel!!.showReplyLayout.observe(this) {
|
||||
if (it) {
|
||||
hideSoftKeyboard()//隐藏软键盘
|
||||
setContentLayoutHeight()
|
||||
} else {
|
||||
val isShow =
|
||||
chatPageViewModel!!.showEmojiLayout.value!! || chatPageViewModel!!.showChooseLayout.value!!
|
||||
if (isShow) {
|
||||
setContentDefaultHeight()
|
||||
}
|
||||
}
|
||||
}
|
||||
chatPageViewModel!!.showEmojiLayout.observe(this) {
|
||||
if (it) {
|
||||
hideSoftKeyboard()//隐藏软键盘
|
||||
setContentLayoutHeight()
|
||||
} else {
|
||||
val isShow =
|
||||
chatPageViewModel!!.showReplyLayout.value!! || chatPageViewModel!!.showChooseLayout.value!!
|
||||
if (isShow) {
|
||||
setContentDefaultHeight()
|
||||
}
|
||||
}
|
||||
}
|
||||
chatPageViewModel!!.showChooseLayout.observe(this) {
|
||||
if (it) {
|
||||
hideSoftKeyboard()//隐藏软键盘
|
||||
setContentLayoutHeight()
|
||||
} else {
|
||||
val isShow =
|
||||
chatPageViewModel!!.showEmojiLayout.value!! || chatPageViewModel!!.showReplyLayout.value!!
|
||||
if (isShow) {
|
||||
setContentDefaultHeight()
|
||||
}
|
||||
}
|
||||
}
|
||||
chatPageViewModel!!.showLoadDialog.observe(this) {
|
||||
if (it) {
|
||||
//显示loading
|
||||
mLoading = LoadingDialog.Builder(this)
|
||||
.setCancelOutside(false)
|
||||
.setCancelable(false)
|
||||
.setMessage("上传中...")
|
||||
.create()
|
||||
mLoading!!.show()
|
||||
} else {
|
||||
//隐藏loading
|
||||
mLoading?.dismiss()
|
||||
mLoading = null
|
||||
}
|
||||
}
|
||||
mBinding.wvView.setTextSize(14F, isSp = true)
|
||||
mBinding.wvView.setAutoFitTextSize(true)
|
||||
mBinding.wvView.setOnItemSelectedListener(object : WheelView.OnItemSelectedListener {
|
||||
@ -91,6 +124,7 @@ class ChatActivity : BaseActivity() {
|
||||
mBinding.etMsg.setText(data.toString())
|
||||
}
|
||||
})
|
||||
|
||||
chatPageViewModel!!.chooseType.observe(this) {
|
||||
when (it) {
|
||||
PickerType.TYPE_PIC -> {
|
||||
@ -121,7 +155,7 @@ class ChatActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
chatPageViewModel!!.scrollListToBottom.observe(this) {
|
||||
Log.e("TAG", "bindView:滚动 ${it} ")
|
||||
Log.e("TAG", "bindView:滚动 $it ")
|
||||
if (it) {
|
||||
val layoutManager = mBinding.rlvChats.layoutManager as LinearLayoutManager
|
||||
val itemCount = layoutManager.itemCount
|
||||
@ -136,14 +170,24 @@ class ChatActivity : BaseActivity() {
|
||||
chatPageViewModel!!.scrollListToBottom.value = false
|
||||
}
|
||||
}
|
||||
mBinding.llBottomLayout.visibility = View.VISIBLE
|
||||
mBinding.rlBottom.visibility = View.GONE
|
||||
mBinding.rlvChats.viewTreeObserver.addOnGlobalLayoutListener {
|
||||
mContentHeight = mBinding.rlvChats.height
|
||||
}
|
||||
|
||||
mBinding.llBottomLayout.viewTreeObserver.addOnGlobalLayoutListener {
|
||||
if (mBinding.llBottomLayout.height == 0) {
|
||||
bottomHeight = DensityUtils.dp2px(this@ChatActivity, 300F)
|
||||
} else {
|
||||
bottomHeight = mBinding.llBottomLayout.height
|
||||
}
|
||||
}
|
||||
SoftKeyBoardListener().setChangeListener(this@ChatActivity,
|
||||
{ h ->
|
||||
mBinding.llBottomLayout.visibility = View.VISIBLE
|
||||
Log.e("ChatActivity", "软键盘: 显示")
|
||||
chatPageViewModel!!.showReplyLayout.value = false
|
||||
chatPageViewModel!!.showEmojiLayout.value = false
|
||||
chatPageViewModel!!.showChooseLayout.value = false
|
||||
mBinding.rlBottom.visibility = View.VISIBLE
|
||||
//重置layout高度
|
||||
val layoutParams = mBinding.rlvChats.layoutParams
|
||||
@ -158,16 +202,17 @@ class ChatActivity : BaseActivity() {
|
||||
0
|
||||
)
|
||||
}, 100)
|
||||
|
||||
|
||||
},
|
||||
{ _ ->
|
||||
Log.e("ChatActivity", "软键盘: 隐藏")
|
||||
val isShowOther =
|
||||
chatPageViewModel!!.showReplyLayout.value!! || chatPageViewModel!!.showEmojiLayout.value!! || chatPageViewModel!!.showChooseLayout.value!!
|
||||
if (!isShowOther) {
|
||||
val layoutParams = mBinding.rlvChats.layoutParams
|
||||
layoutParams.height = mContentHeight
|
||||
mBinding.rlvChats.layoutParams = layoutParams
|
||||
mBinding.llBottomLayout.visibility = View.VISIBLE
|
||||
mBinding.rlBottom.visibility = View.GONE
|
||||
|
||||
}
|
||||
})
|
||||
registerLocalReceiver()
|
||||
}
|
||||
@ -185,6 +230,31 @@ class ChatActivity : BaseActivity() {
|
||||
unregisterReceiver(mLocalReceiver)
|
||||
}
|
||||
|
||||
private fun setContentLayoutHeight() {
|
||||
mBinding.rlBottom.visibility = View.VISIBLE
|
||||
//重置layout高度
|
||||
val layoutParams = mBinding.rlvChats.layoutParams
|
||||
layoutParams.height = mContentHeight - bottomHeight
|
||||
Log.e("ChatActivity", "setContentLayoutHeight: $mContentHeight $bottomHeight")
|
||||
mBinding.rlvChats.layoutParams = layoutParams
|
||||
val layoutManager = mBinding.rlvChats.layoutManager as LinearLayoutManager
|
||||
val itemCount = layoutManager.itemCount
|
||||
//滚动到底部
|
||||
mBinding.rlvChats.postDelayed({
|
||||
layoutManager.scrollToPositionWithOffset(
|
||||
itemCount - 1,
|
||||
0
|
||||
)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
private fun setContentDefaultHeight() {
|
||||
val layoutParams = mBinding.rlvChats.layoutParams
|
||||
layoutParams.height = mContentHeight
|
||||
mBinding.rlvChats.layoutParams = layoutParams
|
||||
mBinding.rlBottom.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
unRegisterLocalReceiver()
|
||||
@ -195,12 +265,17 @@ class ChatActivity : BaseActivity() {
|
||||
when (intent?.action) {
|
||||
ProjectConfig.A_S_MSG_RECEIVER -> {
|
||||
val msg = intent.getStringExtra("msg")
|
||||
Log.e("LocalReceiver", "onReceive: ${msg}")
|
||||
Log.e("LocalReceiver", "onReceive: $msg")
|
||||
chatPageViewModel!!.receiveMsg(msg)
|
||||
}//接收到信息
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//条目点击
|
||||
override fun onItemClick(data: MsgBean) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,8 +10,8 @@ import com.tenlionsoft.baselib.base.BaseActivity
|
||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||
|
||||
class LoginActivity : BaseActivity() {
|
||||
private lateinit var mBinding: ActivityLoginBinding;
|
||||
private var mLoading: LoadingDialog? = null;
|
||||
private lateinit var mBinding: ActivityLoginBinding
|
||||
private var mLoading: LoadingDialog? = null
|
||||
private val loginPageViewModel: LoginPageViewModel by lazy {
|
||||
ViewModelProvider(this)[LoginPageViewModel::class.java]
|
||||
}
|
||||
@ -40,13 +40,13 @@ class LoginActivity : BaseActivity() {
|
||||
}
|
||||
loginPageViewModel.isLoginSuccess.observe(this) {
|
||||
if (it) {
|
||||
// startActivity(Intent(this@LoginActivity, MainActivity::class.java))
|
||||
startActivity(
|
||||
Intent(
|
||||
this@LoginActivity,
|
||||
ChatActivity::class.java
|
||||
).putExtra("fromId", "2")
|
||||
)
|
||||
startActivity(Intent(this@LoginActivity, MainActivity::class.java))
|
||||
// startActivity(
|
||||
// Intent(
|
||||
// this@LoginActivity,
|
||||
// ChatActivity::class.java
|
||||
// ).putExtra("fromId", "2").putExtra("name", "测试")
|
||||
// )
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class MainActivity : BaseActivity() {
|
||||
return@setOnItemSelectedListener true;
|
||||
}//我的
|
||||
}
|
||||
false;
|
||||
false
|
||||
}
|
||||
|
||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
|
@ -17,9 +17,10 @@ import com.tenlionsoft.aimz_k.page.activity.MainActivity
|
||||
import com.tenlionsoft.aimz_k.services.SocketService
|
||||
import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||
|
||||
class MsgFragment : Fragment(), MsgViewModel.OnItemClickListener,
|
||||
class MsgFragment : Fragment(), AdapterItemClickListener<MsgCategoryBean>,
|
||||
MainActivity.OnSocketConnectListener {
|
||||
private lateinit var mMsgBinding: FragmentMsgBinding
|
||||
private var mActivity: MainActivity? = null
|
||||
|
@ -59,6 +59,7 @@ class SocketService : Service(), WsManager.MsgCallBack {
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
||||
private fun registerLocalReceiver() {
|
||||
val intentFilter = IntentFilter()
|
||||
mLocalReceiver = LocalReceiver()
|
||||
|
@ -2,6 +2,9 @@ package com.tenlionsoft.aimz_k.viewmodel
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
@ -15,6 +18,7 @@ import com.tenlionsoft.aimz_k.adapter.ChatMsgAdapter
|
||||
import com.tenlionsoft.aimz_k.model.BodyContent
|
||||
import com.tenlionsoft.aimz_k.model.CoverSealedBean
|
||||
import com.tenlionsoft.aimz_k.model.DbManager
|
||||
import com.tenlionsoft.aimz_k.model.FileDataBean
|
||||
import com.tenlionsoft.aimz_k.model.MsgBean
|
||||
import com.tenlionsoft.aimz_k.model.MsgConvertBean
|
||||
import com.tenlionsoft.aimz_k.model.PickerType
|
||||
@ -23,9 +27,11 @@ import com.tenlionsoft.aimz_k.model.Sender
|
||||
import com.tenlionsoft.aimz_k.net.UserApi
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.net.ExParse
|
||||
import com.tenlionsoft.baselib.net.RetrofitClient
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import com.tenlionsoft.baselib.utils.TimeUtils
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -34,7 +40,6 @@ import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.asRequestBody
|
||||
|
||||
|
||||
class ChatPageViewModel(
|
||||
private val fromId: String,
|
||||
private val toId: String,
|
||||
@ -51,7 +56,34 @@ class ChatPageViewModel(
|
||||
private val retrofitClient = RetrofitClient.getInstance(context)
|
||||
private val netApi = retrofitClient.create(UserApi::class.java)
|
||||
var adapter: ChatMsgAdapter = ChatMsgAdapter(_msgList.value ?: emptyList(), this)
|
||||
var onItemClickListener: AdapterItemClickListener<MsgBean>? = null
|
||||
private val mGson: Gson = Gson()
|
||||
private var msgHandlerList: ArrayList<MsgConvertBean> = arrayListOf()
|
||||
|
||||
private val handler = object : Handler(Looper.getMainLooper()) {
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
val mBean: MsgConvertBean = msg.obj as MsgConvertBean
|
||||
val isExist = msgHandlerList.contains(mBean)
|
||||
if (isExist) {
|
||||
// 更新数据库 发送失败
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val mDao = DbManager.db.msgDao()
|
||||
val cDao = DbManager.db.categoryDao()
|
||||
mDao.updateStatus(mBean.messageId, ProjectConfig.MSG_SEND_FAIL)
|
||||
cDao.updateStatus(mBean.sender.senderId!!, ProjectConfig.MSG_SEND_FAIL)
|
||||
}
|
||||
for (item in _msgList.value!!) {
|
||||
if (item.messageId == mBean.messageId) {
|
||||
item.status = ProjectConfig.MSG_SEND_FAIL
|
||||
}
|
||||
}
|
||||
adapter.setData(_msgList.value!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
Log.e("ChatPageViewModel", "Init: ${showSendBtn.value}")
|
||||
@ -78,20 +110,18 @@ class ChatPageViewModel(
|
||||
}
|
||||
|
||||
fun onShowReplyLayout() {
|
||||
showReplyLayout.value = !showReplyLayout.value!!
|
||||
showEmojiLayout.value = false
|
||||
showChooseLayout.value = false
|
||||
showSoftKeyboard.value = !showReplyLayout.value!!
|
||||
showReplyLayout.value = !showReplyLayout.value!!
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换emoji layout
|
||||
*/
|
||||
fun onShowEmojiLayout() {
|
||||
showEmojiLayout.value = !showEmojiLayout.value!!
|
||||
showChooseLayout.value = false
|
||||
showReplyLayout.value = false
|
||||
showSoftKeyboard.value = !showEmojiLayout.value!!
|
||||
showEmojiLayout.value = !showEmojiLayout.value!!
|
||||
}
|
||||
|
||||
|
||||
@ -99,10 +129,9 @@ class ChatPageViewModel(
|
||||
* 切换选择layout
|
||||
*/
|
||||
fun onShowChooseLayout() {
|
||||
showChooseLayout.value = !showChooseLayout.value!!
|
||||
showEmojiLayout.value = false
|
||||
showReplyLayout.value = false
|
||||
showSoftKeyboard.value = !showChooseLayout.value!!
|
||||
showChooseLayout.value = !showChooseLayout.value!!
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,11 +163,83 @@ class ChatPageViewModel(
|
||||
return
|
||||
}
|
||||
viewModelScope.launch {
|
||||
doUploadImgs(list)
|
||||
showLoadDialog.value = true
|
||||
doUploadImages(list)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun doUploadImgs(list: List<ImageMeta?>) {
|
||||
|
||||
/**
|
||||
* 上传视频
|
||||
*/
|
||||
fun uploadVideo(meta: VideoMeta) {
|
||||
viewModelScope.launch {
|
||||
showLoadDialog.value = true
|
||||
doUploadVideo(meta)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
fun uploadFiles(meta: FileMeta) {
|
||||
viewModelScope.launch {
|
||||
showLoadDialog.value = true
|
||||
doUploadFile(meta)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun doUploadVideo(meta: VideoMeta) {
|
||||
try {
|
||||
val requestFile: RequestBody =
|
||||
meta.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
val body: MultipartBody.Part =
|
||||
MultipartBody.Part.createFormData(
|
||||
"video",
|
||||
meta.file!!.getName(),
|
||||
requestFile
|
||||
)
|
||||
|
||||
val bean = retrofitClient.makeApiCall {
|
||||
netApi.doUploadVideo(body)
|
||||
}
|
||||
if (bean.code == 200) {
|
||||
sendMedia(ProjectConfig.MSG_VIDEO, bean.data)
|
||||
}
|
||||
showLoadDialog.value = false
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
showLoadDialog.value = false
|
||||
ExParse.parse(e)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun doUploadFile(meta: FileMeta) {
|
||||
try {
|
||||
val requestFile: RequestBody =
|
||||
meta.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
val body: MultipartBody.Part =
|
||||
MultipartBody.Part.createFormData(
|
||||
"file",
|
||||
meta.file!!.getName(),
|
||||
requestFile
|
||||
)
|
||||
val bean = retrofitClient.makeApiCall {
|
||||
netApi.doUploadFile(body)
|
||||
}
|
||||
if (bean.code == 200) {
|
||||
sendMedia(ProjectConfig.MSG_FILE, bean.data)
|
||||
}
|
||||
showLoadDialog.value = false
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
showLoadDialog.value = false
|
||||
ExParse.parse(e)
|
||||
}
|
||||
}
|
||||
|
||||
private var count: Int = 1
|
||||
private suspend fun doUploadImages(list: List<ImageMeta?>) {
|
||||
try {
|
||||
for (item in list) {
|
||||
if (item != null) {
|
||||
@ -146,7 +247,7 @@ class ChatPageViewModel(
|
||||
item.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
val body: MultipartBody.Part =
|
||||
MultipartBody.Part.createFormData(
|
||||
"audio",
|
||||
"image",
|
||||
item.file!!.getName(),
|
||||
requestFile
|
||||
)
|
||||
@ -154,35 +255,40 @@ class ChatPageViewModel(
|
||||
val bean = retrofitClient.makeApiCall {
|
||||
netApi.doUploadImage(body)
|
||||
}
|
||||
Log.e("ChatPageViewModel", "doUploadImgs: $bean")
|
||||
if (bean.code == 200) {
|
||||
//上传成功
|
||||
//TODO 构建消息实体
|
||||
//TODO 发送消息
|
||||
//
|
||||
} else {
|
||||
//TODO 上传失败
|
||||
sendMedia(ProjectConfig.MSG_IMG, bean.data)
|
||||
}
|
||||
++count
|
||||
}
|
||||
}
|
||||
if (count == list.size) {
|
||||
showLoadDialog.value = false
|
||||
count = 1
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
showLoadDialog.value = false
|
||||
count = 1
|
||||
ExParse.parse(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传视频
|
||||
*/
|
||||
fun uploadVideo(meta: VideoMeta) {
|
||||
|
||||
//发送 图片/视频/音频/文件
|
||||
private fun sendMedia(type: String, data: FileDataBean) {
|
||||
val intent = Intent(ProjectConfig.A_S_MSG_SEND)
|
||||
val b = buildSendMediaBean(type, data)
|
||||
viewModelScope.launch {
|
||||
val msgBean = insertMsgBeanToDb(b)
|
||||
_msgList.value = _msgList.value?.plus(msgBean)
|
||||
adapter.setData(_msgList.value!!)
|
||||
}
|
||||
intent.putExtra("msgBean", b)
|
||||
context.sendBroadcast(intent)
|
||||
scrollListToBottom.value = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
fun uploadFiles(meta: FileMeta) {
|
||||
|
||||
}
|
||||
|
||||
//刷新
|
||||
private fun refresh() {
|
||||
@ -198,6 +304,7 @@ class ChatPageViewModel(
|
||||
_msgList.value = _msgList.value?.plus(msgBean)
|
||||
adapter.setData(_msgList.value!!)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送文本信息
|
||||
*/
|
||||
@ -210,6 +317,10 @@ class ChatPageViewModel(
|
||||
_msgList.value = _msgList.value?.plus(msgBean)
|
||||
adapter.setData(_msgList.value!!)
|
||||
}
|
||||
// 保存发送信息到消息队列
|
||||
//添加到消息队列
|
||||
|
||||
sendHandlerToLooper(b)
|
||||
intent.putExtra("msgBean", b)
|
||||
v.context.sendBroadcast(intent)
|
||||
txtMsg.value = ""
|
||||
@ -228,11 +339,18 @@ class ChatPageViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendHandlerToLooper(b: MsgConvertBean) {
|
||||
msgHandlerList.add(b)
|
||||
val msg = Message()
|
||||
msg.what = b.timestamp.toInt()
|
||||
msg.obj = b
|
||||
handler.sendMessageDelayed(msg, 5000)
|
||||
}
|
||||
|
||||
//收到消息
|
||||
fun receiveMsg(msg: String?) {
|
||||
if (!msg.isNullOrEmpty()) {
|
||||
val bean = ConvertBeanUtils.covertBean(msg)
|
||||
when (bean) {
|
||||
when (val bean = ConvertBeanUtils.covertBean(msg)) {
|
||||
//消息状态
|
||||
is CoverSealedBean.StateBean -> {
|
||||
viewModelScope.launch {
|
||||
@ -244,6 +362,9 @@ class ChatPageViewModel(
|
||||
dao.updateStatus(bean.data.messageId, statusType)
|
||||
cDao.updateStatus(bean.data.sender.senderId!!, statusType)
|
||||
}
|
||||
//删除队列里面的Bean
|
||||
msgHandlerList.removeIf { it.messageId == bean.data.messageId }
|
||||
handler.removeMessages(bean.data.timestamp.toInt())
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
@ -275,7 +396,7 @@ class ChatPageViewModel(
|
||||
context.sendBroadcast(intent)
|
||||
}
|
||||
|
||||
//构建发送实体
|
||||
//构建文字发送实体
|
||||
private fun buildSendBean(type: String): MsgConvertBean {
|
||||
val bodyBean = BodyContent(content = txtMsg.value, null, null)
|
||||
val body = mGson.toJson(bodyBean)
|
||||
@ -298,6 +419,31 @@ class ChatPageViewModel(
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
//构建 图片/视频/文件发送实体
|
||||
private fun buildSendMediaBean(type: String, fileBean: FileDataBean): MsgConvertBean {
|
||||
val bodyBean = BodyContent(content = mGson.toJson(fileBean), null, null)
|
||||
val body = mGson.toJson(bodyBean)
|
||||
return MsgConvertBean(
|
||||
body = body,
|
||||
customMessageType = "",
|
||||
messageId = TimeUtils.getNowDateMillis().toString(),
|
||||
messageType = type,
|
||||
metadata = "",
|
||||
timestamp = TimeUtils.getNowDateMillis(),
|
||||
sender = Sender(
|
||||
senderId = SpUtils.getId(),
|
||||
senderType = ""
|
||||
),
|
||||
receiver = Receiver(
|
||||
receiverId = fromId,
|
||||
receiverType = "SINGLE_USER"
|
||||
),
|
||||
status = ProjectConfig.MSG_SEND_ING,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
//构建状态信息
|
||||
private fun buildStatusBean(messageId: String): MsgConvertBean {
|
||||
val bodyBean = BodyContent(content = null, msg = "", statusType = "SUCCESS_RECEIVED")
|
||||
@ -320,4 +466,7 @@ class ChatPageViewModel(
|
||||
status = "",
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,7 +37,7 @@ class LoginPageViewModel : BaseViewModel() {
|
||||
}
|
||||
|
||||
fun doLogin() {
|
||||
isLoginSuccess.value = true
|
||||
// isLoginSuccess.value= true
|
||||
val isLegal = checkParams();
|
||||
if (isLegal) {
|
||||
viewModelScope.launch {
|
||||
|
@ -19,6 +19,7 @@ import com.tenlionsoft.aimz_k.model.Sender
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import com.tenlionsoft.baselib.utils.TimeUtils
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -26,7 +27,7 @@ import kotlinx.coroutines.withContext
|
||||
class MsgViewModel : ViewModel() {
|
||||
private val _pwdList = MutableLiveData<List<MsgCategoryBean>>()
|
||||
var adapter: CategoryAdapter = CategoryAdapter(_pwdList.value ?: emptyList(), this)
|
||||
var onItemClickListener: OnItemClickListener? = null
|
||||
var onItemClickListener: AdapterItemClickListener<MsgCategoryBean>? = null
|
||||
val isLogining = MutableLiveData(false)
|
||||
private val mGson = Gson()
|
||||
private var mCurrentPage: Int = 1
|
||||
@ -156,8 +157,4 @@ class MsgViewModel : ViewModel() {
|
||||
fun refresh() {
|
||||
getList(true)
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
fun onItemClick(msgCategoryBean: MsgCategoryBean)
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.tenlionsoft.aimz_k.widget
|
||||
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
@ -10,11 +13,18 @@ import androidx.recyclerview.widget.RecyclerView.Adapter
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.google.gson.Gson
|
||||
import com.tenlionsoft.aimz_k.R
|
||||
import com.tenlionsoft.aimz_k.model.BodyContent
|
||||
import com.tenlionsoft.aimz_k.model.FileDataBean
|
||||
import com.tenlionsoft.baselib.contacts.NetConfig
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.model.ImageSize
|
||||
import com.tenlionsoft.baselib.utils.ImageUtils
|
||||
import com.tenlionsoft.baselib.utils.TimeUtils
|
||||
import com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
||||
|
||||
|
||||
object BindingUtils {
|
||||
@ -61,9 +71,133 @@ object BindingUtils {
|
||||
} else {
|
||||
val gson = Gson()
|
||||
val body = gson.fromJson(str, BodyContent::class.java)
|
||||
val contains = body.content!!.contains("fileName")
|
||||
if (contains) {
|
||||
tv.text = "文件"
|
||||
} else {
|
||||
tv.text = body.content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("jsonConvertMsgFileIcon")
|
||||
@JvmStatic
|
||||
fun jsonConvertFileIcon(iv: ImageView, str: String?) {
|
||||
if (str.isNullOrEmpty()) {
|
||||
iv.visibility = View.GONE
|
||||
} else {
|
||||
iv.visibility = View.VISIBLE
|
||||
val gson = Gson()
|
||||
val body = gson.fromJson(str, BodyContent::class.java)
|
||||
val contains = body.content!!.contains("fileName")
|
||||
if (contains) {
|
||||
val fileDataBean = gson.fromJson(body.content, FileDataBean::class.java)
|
||||
if (!fileDataBean.fileName.isNullOrEmpty()) {
|
||||
iv.visibility = View.VISIBLE
|
||||
val suffix = fileDataBean.fileName!!.substring(
|
||||
fileDataBean.fileName!!.lastIndexOf("."),
|
||||
fileDataBean.fileName!!.length
|
||||
)
|
||||
Log.e("BindingUtils", "jsonConvertFileIcon: $suffix")
|
||||
var id = R.drawable.ic_audio
|
||||
when (suffix) {
|
||||
".zip", ".rar", ".7z", ".gz", ".xz" -> iv.setImageResource(R.drawable.ic_zip)
|
||||
".png", ".jpg", ".jpeg", ".svg", ".gif" -> iv.setImageResource(R.drawable.ic_image)
|
||||
".doc", ".docx", ".wps", ".wpt" -> iv.setImageResource(R.drawable.ic_word)
|
||||
".xls", ".xlsx", ".et", ".ett" -> iv.setImageResource(R.drawable.ic_excel)
|
||||
".pdf" -> iv.setImageResource(R.drawable.ic_pdf)
|
||||
else -> iv.setImageResource(R.drawable.ic_file)
|
||||
}
|
||||
} else {
|
||||
iv.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
iv.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("jsonConvertMsgFileName")
|
||||
@JvmStatic
|
||||
fun jsonConvertFileName(tv: TextView, str: String?) {
|
||||
if (str.isNullOrEmpty()) {
|
||||
tv.text = ""
|
||||
} else {
|
||||
val gson = Gson()
|
||||
val body = gson.fromJson(str, BodyContent::class.java)
|
||||
val contains = body.content!!.contains("fileName")
|
||||
if (contains) {
|
||||
val fileBean = gson.fromJson(body.content, FileDataBean::class.java)
|
||||
tv.text = fileBean.fileName
|
||||
} else {
|
||||
tv.text = body.content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("jsonConvertMsgAudioImg")
|
||||
@JvmStatic
|
||||
fun jsonConvertAudioCover(iv: ImageView, str: String?) {
|
||||
if (str.isNullOrEmpty()) {
|
||||
iv.setImageResource(com.tenlionsoft.baselib.R.drawable.ic_img_load_err)
|
||||
} else {
|
||||
val options: RequestOptions = RequestOptions()
|
||||
.placeholder(com.tenlionsoft.baselib.R.drawable.ic_loading) // 正在加载中的图片
|
||||
.error(com.tenlionsoft.baselib.R.drawable.ic_img_load_err) // 加载失败的图片
|
||||
val gson = Gson()
|
||||
val bodyContent = gson.fromJson<BodyContent>(str, BodyContent::class.java)
|
||||
|
||||
val fileBean = gson.fromJson(bodyContent.content, FileDataBean::class.java)
|
||||
Glide.with(iv.context)
|
||||
.load(NetConfig.MAIN_URL + fileBean.fileUrl) // 图片地址
|
||||
.apply(options)
|
||||
.into(object : CustomTarget<Drawable?>() {
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
transition: Transition<in Drawable?>?
|
||||
) {
|
||||
val imageSize: ImageSize? =
|
||||
ImageUtils.getImageSize((resource as BitmapDrawable).bitmap)
|
||||
if (imageSize != null) {
|
||||
val imageLP = iv.layoutParams
|
||||
imageLP?.width = imageSize.getWidth()
|
||||
imageLP?.height = imageSize.getHeight()
|
||||
iv.setLayoutParams(imageLP)
|
||||
Glide.with(iv.context)
|
||||
.load(resource)
|
||||
.apply(options) // 参数
|
||||
.into(iv)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadCleared(placeholder: Drawable?) {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("jsonConvertMsgImgBody")
|
||||
@JvmStatic
|
||||
fun jsonConvertImg(view: BubbleImageView, str: String?) {
|
||||
if (str.isNullOrEmpty()) {
|
||||
view.setImageResource(com.tenlionsoft.baselib.R.drawable.ic_load_error)
|
||||
} else {
|
||||
val gson = Gson()
|
||||
val body = gson.fromJson(str, BodyContent::class.java)
|
||||
val fileData = gson.fromJson(body.content, FileDataBean::class.java)
|
||||
|
||||
val requestOptions = RequestOptions()
|
||||
.error(R.drawable.app_logo_small)
|
||||
.placeholder(R.drawable.app_logo_small)
|
||||
.skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerInside()
|
||||
Glide.with(view.context)
|
||||
.load(NetConfig.MAIN_URL + fileData.fileUrl)
|
||||
.apply(requestOptions)
|
||||
.into(view)
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("millConvertDate")
|
||||
@JvmStatic
|
||||
|
BIN
app/src/main/res/drawable-xhdpi/ic_audio.png
Normal file
After Width: | Height: | Size: 798 B |
BIN
app/src/main/res/drawable-xhdpi/ic_excel.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_file.png
Normal file
After Width: | Height: | Size: 556 B |
BIN
app/src/main/res/drawable-xhdpi/ic_image.png
Normal file
After Width: | Height: | Size: 805 B |
BIN
app/src/main/res/drawable-xhdpi/ic_mp.png
Normal file
After Width: | Height: | Size: 1014 B |
BIN
app/src/main/res/drawable-xhdpi/ic_pdf.png
Normal file
After Width: | Height: | Size: 961 B |
BIN
app/src/main/res/drawable-xhdpi/ic_ppt.png
Normal file
After Width: | Height: | Size: 891 B |
BIN
app/src/main/res/drawable-xhdpi/ic_psd.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_word.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_zip.png
Normal file
After Width: | Height: | Size: 830 B |
@ -73,7 +73,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/green"
|
||||
tools:listitem="@layout/item_msg_my" />
|
||||
|
||||
|
||||
|
94
app/src/main/res/layout/item_msg_my_file.xml
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pos"
|
||||
type="Integer" />
|
||||
|
||||
<variable
|
||||
name="bean"
|
||||
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
||||
|
||||
<variable
|
||||
name="state"
|
||||
type="String" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_margin="5dp"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_toLeftOf="@id/tv_content">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_sending"
|
||||
isShowLoading="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminateBehavior="repeat"
|
||||
android:indeterminateDrawable="@drawable/anim_loading" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_msg_state_fail"
|
||||
isShowFail="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@drawable/msg_state_fail_resend"
|
||||
tools:visibility="visible" />
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="@drawable/ic_message_text_send"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
jsonConvertMsgFileIcon="@{bean.body}"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:scaleType="fitXY" />
|
||||
|
||||
<TextView
|
||||
jsonConvertMsgFileName="@{bean.body}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="文件名称文件名称文件名称文件名称文件名称文件名称.jpg" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_user_icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_user_default" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pos"
|
||||
type="Integer" />
|
||||
@ -11,6 +12,7 @@
|
||||
<variable
|
||||
name="bean"
|
||||
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
||||
|
||||
<variable
|
||||
name="state"
|
||||
type="String" />
|
||||
@ -41,19 +43,19 @@
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_sending"
|
||||
isShowLoading="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_centerInParent="true"
|
||||
isShowLoading="@{state}"
|
||||
android:indeterminateBehavior="repeat"
|
||||
android:indeterminateDrawable="@drawable/anim_loading" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_msg_state_fail"
|
||||
isShowFail="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_centerInParent="true"
|
||||
isShowFail="@{state}"
|
||||
android:src="@drawable/msg_state_fail_resend"
|
||||
tools:visibility="visible" />
|
||||
</RelativeLayout>
|
||||
@ -68,6 +70,7 @@
|
||||
|
||||
<com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
||||
android:id="@+id/iv_content"
|
||||
jsonConvertMsgImgBody="@{bean.body}"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_alignParentStart="true"
|
||||
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pos"
|
||||
type="Integer" />
|
||||
@ -11,6 +12,7 @@
|
||||
<variable
|
||||
name="bean"
|
||||
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
||||
|
||||
<variable
|
||||
name="state"
|
||||
type="String" />>
|
||||
@ -41,18 +43,18 @@
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_sending"
|
||||
isShowLoading="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
isShowLoading="@{state}"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminateBehavior="repeat"
|
||||
android:indeterminateDrawable="@drawable/anim_loading" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_msg_state_fail"
|
||||
isShowFail="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
isShowFail="@{state}"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@drawable/msg_state_fail_resend"
|
||||
tools:visibility="visible" />
|
||||
@ -68,8 +70,9 @@
|
||||
|
||||
<com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
||||
android:id="@+id/iv_content"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
jsonConvertMsgAudioImg="@{bean.body}"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="0dp"
|
||||
android:adjustViewBounds="true"
|
||||
|
83
app/src/main/res/layout/item_msg_other_file.xml
Normal file
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="pos"
|
||||
type="Integer" />
|
||||
|
||||
<variable
|
||||
name="bean"
|
||||
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
||||
|
||||
<variable
|
||||
name="state"
|
||||
type="String" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:gravity="left"
|
||||
android:padding="8dp">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_user_icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_user_default" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:background="@drawable/ic_message_text_receive"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
jsonConvertMsgFileName="@{bean.body}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
tools:text="文件名称文件名称文件名称文件名称文件名称文件名称.jpg" />
|
||||
|
||||
<ImageView
|
||||
jsonConvertMsgFileIcon="@{bean.body}"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:scaleType="fitXY" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginTop="5dp">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_sending"
|
||||
isShowLoading="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminateBehavior="repeat"
|
||||
android:indeterminateDrawable="@drawable/anim_loading" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_msg_state_fail"
|
||||
isShowFail="@{state}"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@drawable/msg_state_fail_resend"
|
||||
tools:visibility="visible" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</layout>
|
@ -47,6 +47,7 @@
|
||||
android:layout_marginStart="0dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop"
|
||||
jsonConvertMsgImgBody="@{bean.body}"
|
||||
android:transitionName="sharedView"
|
||||
app:angle="6dp"
|
||||
app:arrowHeight="8dp"
|
||||
|
@ -45,6 +45,7 @@
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_alignParentStart="true"
|
||||
jsonConvertMsgAudioImg="@{bean.body}"
|
||||
android:layout_marginStart="0dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop"
|
||||
|
@ -19,8 +19,9 @@ object ProjectConfig {
|
||||
//消息类型
|
||||
const val MSG_TEXT = "MSG_TEXT"
|
||||
const val MSG_FILE = "MSG_FILE"
|
||||
const val MSG_IMG = "MSG_IMG"
|
||||
const val MSG_IMG = "MSG_IMAGE"
|
||||
const val MSG_VIDEO = "MSG_VIDEO"
|
||||
const val MSG_AUDIO = "MSG_AUDIO"
|
||||
const val MSG_STATUS = "STATUS" //状态消息
|
||||
const val MSG_SEND_ING: String = "PENDING"//11 //发送中
|
||||
const val MSG_SEND_FAIL: String = "ERROR"//12 //发送失败
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.tenlionsoft.baselib.model
|
||||
|
||||
class ImageSize {
|
||||
private var width = 0
|
||||
private var height = 0
|
||||
fun getWidth(): Int {
|
||||
return width
|
||||
}
|
||||
|
||||
fun setWidth(width: Int) {
|
||||
this.width = width
|
||||
}
|
||||
|
||||
fun getHeight(): Int {
|
||||
return height
|
||||
}
|
||||
|
||||
fun setHeight(height: Int) {
|
||||
this.height = height
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.tenlionsoft.baselib.net
|
||||
|
||||
import android.util.Log
|
||||
import com.tenlionsoft.baselib.contacts.NetConfig
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import okhttp3.HttpUrl
|
||||
@ -19,7 +20,10 @@ class BaseUrlInterceptor : Interceptor {
|
||||
val oldHttpUrl = request.url;
|
||||
val headers = request.headers("project");
|
||||
//公共Token header
|
||||
if (headers.indexOf("token") != -1) {
|
||||
val tokens = request.headers("token")
|
||||
Log.e("BaseUrlInterceptor", "intercept: $tokens")
|
||||
if (tokens.isNotEmpty()) {
|
||||
Log.e("BaseUrlInterceptor", "intercept: 添加公共Header")
|
||||
builder.removeHeader("token")
|
||||
builder.addHeader("X-WG-TOKEN", SpUtils.getToken())
|
||||
builder.addHeader("X-WG-TYPE", "APP")
|
||||
@ -43,7 +47,7 @@ class BaseUrlInterceptor : Interceptor {
|
||||
.build();
|
||||
return chain.proceed(builder.url(newFullUrl).build());
|
||||
} else {
|
||||
return chain.proceed(request);
|
||||
return chain.proceed(builder.url(oldHttpUrl).build());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.tenlionsoft.baselib.utils
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import com.tenlionsoft.baselib.model.ImageSize
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
|
||||
object ImageUtils {
|
||||
fun getImageSize(bitmap: Bitmap?): ImageSize? {
|
||||
val imageSize: ImageSize = ImageSize()
|
||||
if (null == bitmap || bitmap.isRecycled) {
|
||||
return null
|
||||
}
|
||||
val baos = ByteArrayOutputStream()
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
|
||||
val byteTmp = baos.toByteArray()
|
||||
try {
|
||||
baos.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
val bitmapOptions = BitmapFactory.Options()
|
||||
bitmapOptions.inJustDecodeBounds = true
|
||||
BitmapFactory.decodeByteArray(byteTmp, 0, byteTmp.size, bitmapOptions)
|
||||
val outWidth = bitmapOptions.outWidth
|
||||
val outHeight = bitmapOptions.outHeight
|
||||
val maxWidth = 400
|
||||
val maxHeight = 400
|
||||
val minWidth = 150
|
||||
val minHeight = 150
|
||||
if (outWidth / maxWidth > outHeight / maxHeight) { //
|
||||
if (outWidth >= maxWidth) { //
|
||||
imageSize.setWidth(maxWidth)
|
||||
imageSize.setHeight(outHeight * maxWidth / outWidth)
|
||||
} else {
|
||||
imageSize.setWidth(outWidth)
|
||||
imageSize.setHeight(outHeight)
|
||||
}
|
||||
if (outHeight < minHeight) {
|
||||
imageSize.setHeight(minHeight)
|
||||
val width = outWidth * minHeight / outHeight
|
||||
imageSize.setWidth(Math.min(width, maxWidth))
|
||||
}
|
||||
} else {
|
||||
if (outHeight >= maxHeight) {
|
||||
imageSize.setHeight(maxHeight)
|
||||
imageSize.setWidth(outWidth * maxHeight / outHeight)
|
||||
} else {
|
||||
imageSize.setHeight(outHeight)
|
||||
imageSize.setWidth(outWidth)
|
||||
}
|
||||
if (outWidth < minWidth) {
|
||||
imageSize.setWidth(minWidth)
|
||||
val height = outHeight * minWidth / outWidth
|
||||
imageSize.setHeight(Math.min(height, maxHeight))
|
||||
}
|
||||
}
|
||||
|
||||
return imageSize
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.tenlionsoft.baselib.widget
|
||||
|
||||
interface AdapterItemClickListener<D> {
|
||||
fun onItemClick(data: D)
|
||||
}
|
BIN
baselib/src/main/res/drawable-xhdpi/ic_img_load_err.png
Normal file
After Width: | Height: | Size: 8.3 KiB |