发送文件,图片,视频,处理失败
@ -5,10 +5,12 @@ import android.view.ViewGroup
|
|||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyAudioBinding
|
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyAudioBinding
|
||||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyBinding
|
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.ItemMsgMyImgBinding
|
||||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyVideoBinding
|
import com.tenlionsoft.aimz_k.databinding.ItemMsgMyVideoBinding
|
||||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherAudioBinding
|
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherAudioBinding
|
||||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherBinding
|
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.ItemMsgOtherImgBinding
|
||||||
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherVideoBinding
|
import com.tenlionsoft.aimz_k.databinding.ItemMsgOtherVideoBinding
|
||||||
import com.tenlionsoft.aimz_k.model.MsgBean
|
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.aimz_k.viewmodel.ChatPageViewModel
|
||||||
import com.tenlionsoft.baselib.base.BaseBindingAdapter
|
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) {
|
BaseBindingAdapter<MsgBean, ViewDataBinding>(datas) {
|
||||||
|
|
||||||
override fun getItemBinding(parent: ViewGroup, viewType: Int): ViewDataBinding {
|
override fun getItemBinding(parent: ViewGroup, viewType: Int): ViewDataBinding {
|
||||||
when (viewType) {
|
when (viewType) {
|
||||||
MsgTypeStateEnum.MSG_TO_OTHER_TXT -> {
|
//发送文本
|
||||||
|
MsgTypeStateEnum.MSG_TO_OTHER_TXT ->
|
||||||
return ItemMsgOtherBinding.inflate(
|
return ItemMsgOtherBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}//发送文本
|
|
||||||
MsgTypeStateEnum.MSG_FROM_OTHER_TXT -> {
|
//收到文本信息
|
||||||
|
MsgTypeStateEnum.MSG_FROM_OTHER_TXT ->
|
||||||
return ItemMsgMyBinding.inflate(
|
return ItemMsgMyBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}//收到文本信息
|
|
||||||
MsgTypeStateEnum.MSG_TO_OTHER_MOVIE -> {
|
//发送视频
|
||||||
return ItemMsgMyVideoBinding.inflate(
|
MsgTypeStateEnum.MSG_TO_OTHER_MOVIE ->
|
||||||
LayoutInflater.from(parent.context),
|
|
||||||
parent,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}//发送视频
|
|
||||||
MsgTypeStateEnum.MSG_FROM_OTHER_MOVIE -> {
|
|
||||||
return ItemMsgOtherVideoBinding.inflate(
|
return ItemMsgOtherVideoBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}//收到视频
|
|
||||||
MsgTypeStateEnum.MSG_TO_OTHER_IMG -> {
|
//收到视频
|
||||||
return ItemMsgMyImgBinding.inflate(
|
MsgTypeStateEnum.MSG_FROM_OTHER_MOVIE ->
|
||||||
|
return ItemMsgMyVideoBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}//发送图片
|
|
||||||
MsgTypeStateEnum.MSG_FROM_OTHER_IMG -> {
|
//发送图片
|
||||||
|
MsgTypeStateEnum.MSG_TO_OTHER_IMG ->
|
||||||
return ItemMsgOtherImgBinding.inflate(
|
return ItemMsgOtherImgBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
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(
|
return ItemMsgMyAudioBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}//语音
|
//语音
|
||||||
MsgTypeStateEnum.MSG_FROM_OTHER_VOICE -> {
|
MsgTypeStateEnum.MSG_FROM_OTHER_VOICE ->
|
||||||
return ItemMsgOtherAudioBinding.inflate(
|
return ItemMsgOtherAudioBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
parent,
|
parent,
|
||||||
false
|
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 -> {
|
else -> {
|
||||||
throw IllegalArgumentException("Invalid view type")
|
throw IllegalArgumentException("Invalid view type")
|
||||||
}
|
}
|
||||||
@ -89,6 +114,9 @@ class ChatMsgAdapter(datas: List<MsgBean>, viewModel: ChatPageViewModel) :
|
|||||||
|
|
||||||
override fun bindItem(holder: BaseViewHolder<ViewDataBinding>, position: Int) {
|
override fun bindItem(holder: BaseViewHolder<ViewDataBinding>, position: Int) {
|
||||||
val itemType = getItemViewType(position)
|
val itemType = getItemViewType(position)
|
||||||
|
holder.binding.root.setOnClickListener {
|
||||||
|
viewModel.onItemClickListener?.onItemClick(list[position])
|
||||||
|
}
|
||||||
when (itemType) {
|
when (itemType) {
|
||||||
//发送文本
|
//发送文本
|
||||||
MsgTypeStateEnum.MSG_TO_OTHER_TXT -> {
|
MsgTypeStateEnum.MSG_TO_OTHER_TXT -> {
|
||||||
@ -104,28 +132,28 @@ class ChatMsgAdapter(datas: List<MsgBean>, viewModel: ChatPageViewModel) :
|
|||||||
}
|
}
|
||||||
//发送视频
|
//发送视频
|
||||||
MsgTypeStateEnum.MSG_TO_OTHER_MOVIE -> {
|
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).pos = position
|
||||||
(holder.binding as ItemMsgOtherVideoBinding).bean = list[position]
|
(holder.binding as ItemMsgOtherVideoBinding).bean = list[position]
|
||||||
(holder.binding as ItemMsgOtherVideoBinding).state = list[position].status
|
(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 -> {
|
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).pos = position
|
||||||
(holder.binding as ItemMsgOtherImgBinding).bean = list[position]
|
(holder.binding as ItemMsgOtherImgBinding).bean = list[position]
|
||||||
(holder.binding as ItemMsgOtherImgBinding).state = list[position].status
|
(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 -> {
|
MsgTypeStateEnum.MSG_TO_OTHER_VOICE -> {
|
||||||
(holder.binding as ItemMsgMyAudioBinding).pos = position
|
(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).bean = list[position]
|
||||||
(holder.binding as ItemMsgOtherAudioBinding).state = list[position].status
|
(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 -> {
|
else -> {
|
||||||
throw IllegalArgumentException("Invalid view type")
|
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
|
package com.tenlionsoft.aimz_k.net
|
||||||
|
|
||||||
import com.tenlionsoft.aimz_k.model.BaseSuccessBean
|
import com.tenlionsoft.aimz_k.model.BaseSuccessBean
|
||||||
|
import com.tenlionsoft.aimz_k.model.FileUploadStateBean
|
||||||
import com.tenlionsoft.baselib.model.VersionBean
|
import com.tenlionsoft.baselib.model.VersionBean
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
@ -23,6 +24,7 @@ interface UserApi {
|
|||||||
@Headers("Content-Type: application/json", "Accept: application/json", "projectName:usercenter")
|
@Headers("Content-Type: application/json", "Accept: application/json", "projectName:usercenter")
|
||||||
@POST("api/jwt/login")
|
@POST("api/jwt/login")
|
||||||
suspend fun doLogin(@Body user: RequestBody): BaseSuccessBean
|
suspend fun doLogin(@Body user: RequestBody): BaseSuccessBean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登陆Socket系统
|
* 登陆Socket系统
|
||||||
* http://192.168.0.26:8888/system/api/anonymous/login
|
* http://192.168.0.26:8888/system/api/anonymous/login
|
||||||
@ -43,7 +45,7 @@ interface UserApi {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传图片文件
|
* 上传图片
|
||||||
* image
|
* image
|
||||||
*
|
*
|
||||||
* @param file
|
* @param file
|
||||||
@ -52,8 +54,8 @@ interface UserApi {
|
|||||||
*/
|
*/
|
||||||
@Headers("token:need")
|
@Headers("token:need")
|
||||||
@Multipart
|
@Multipart
|
||||||
@POST("app/file/uploadimage")
|
@POST("api/file/upload/image")
|
||||||
suspend fun doUploadImage(@Part file: MultipartBody.Part): BaseSuccessBean
|
suspend fun doUploadImage(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,6 +68,22 @@ interface UserApi {
|
|||||||
*/
|
*/
|
||||||
@Headers("token:need")
|
@Headers("token:need")
|
||||||
@Multipart
|
@Multipart
|
||||||
@POST("app/file/uploadvideo")
|
@POST("api/file/upload/video")
|
||||||
fun doUploadVideo(@Part file: MultipartBody.Part): BaseSuccessBean
|
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.atwa.filepicker.core.FilePicker
|
||||||
import com.tenlionsoft.aimz_k.R
|
import com.tenlionsoft.aimz_k.R
|
||||||
import com.tenlionsoft.aimz_k.databinding.ActivityChatBinding
|
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.model.PickerType
|
||||||
import com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel
|
import com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel
|
||||||
import com.tenlionsoft.baselib.base.BaseActivity
|
import com.tenlionsoft.baselib.base.BaseActivity
|
||||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||||
|
import com.tenlionsoft.baselib.utils.DensityUtils
|
||||||
import com.tenlionsoft.baselib.utils.SpUtils
|
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.SoftKeyBoardListener
|
||||||
import com.tenlionsoft.baselib.widget.wheel.WheelView
|
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 mBinding: ActivityChatBinding
|
||||||
private lateinit var mLocalReceiver: LocalReceiver
|
private lateinit var mLocalReceiver: LocalReceiver
|
||||||
var chatPageViewModel: ChatPageViewModel? = null
|
var chatPageViewModel: ChatPageViewModel? = null
|
||||||
private val filePicker = FilePicker.getInstance(this)
|
private val filePicker = FilePicker.getInstance(this)
|
||||||
private var mContentHeight: Int = 0
|
private var mContentHeight: Int = 0
|
||||||
|
private var mLoading: LoadingDialog? = null;
|
||||||
|
private var bottomHeight = -1
|
||||||
override fun bindView() {
|
override fun bindView() {
|
||||||
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_chat);
|
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_chat);
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||||
@ -43,9 +48,7 @@ class ChatActivity : BaseActivity() {
|
|||||||
|
|
||||||
val fromId = intent.getStringExtra("fromId") //传递过来的接收人
|
val fromId = intent.getStringExtra("fromId") //传递过来的接收人
|
||||||
val name = intent.getStringExtra("name")
|
val name = intent.getStringExtra("name")
|
||||||
if (name.isNullOrEmpty()) {
|
mBinding.tvTitle.text = if (name.isNullOrEmpty()) "临时客户" else name
|
||||||
mBinding.tvTitle.text = "临时客户"
|
|
||||||
}
|
|
||||||
|
|
||||||
chatPageViewModel = ViewModelProvider(this, object : ViewModelProvider.Factory {
|
chatPageViewModel = ViewModelProvider(this, object : ViewModelProvider.Factory {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
@ -54,7 +57,7 @@ class ChatActivity : BaseActivity() {
|
|||||||
) as T
|
) as T
|
||||||
}
|
}
|
||||||
})[ChatPageViewModel::class.java]
|
})[ChatPageViewModel::class.java]
|
||||||
|
chatPageViewModel!!.onItemClickListener = this
|
||||||
mBinding.ivBack.setOnClickListener { finish(); }
|
mBinding.ivBack.setOnClickListener { finish(); }
|
||||||
mBinding.viewModel = chatPageViewModel
|
mBinding.viewModel = chatPageViewModel
|
||||||
mBinding.lifecycleOwner = this
|
mBinding.lifecycleOwner = this
|
||||||
@ -63,27 +66,57 @@ class ChatActivity : BaseActivity() {
|
|||||||
mBinding.etMsg.append(it.emoji)
|
mBinding.etMsg.append(it.emoji)
|
||||||
}
|
}
|
||||||
|
|
||||||
//显示/隐藏软键盘
|
chatPageViewModel!!.showReplyLayout.observe(this) {
|
||||||
// chatPageViewModel!!.showSoftKeyboard.observe(this) {
|
if (it) {
|
||||||
// if (it) {
|
hideSoftKeyboard()//隐藏软键盘
|
||||||
// showSoftKeyBoard(mBinding.etMsg)
|
setContentLayoutHeight()
|
||||||
// chatPageViewModel!!.showChooseLayout.value = false
|
} else {
|
||||||
// chatPageViewModel!!.showEmojiLayout.value = false
|
val isShow =
|
||||||
// chatPageViewModel!!.showReplyLayout.value = false
|
chatPageViewModel!!.showEmojiLayout.value!! || chatPageViewModel!!.showChooseLayout.value!!
|
||||||
// val layoutManager = mBinding.rlvChats.layoutManager as LinearLayoutManager
|
if (isShow) {
|
||||||
// val itemCount = layoutManager.itemCount
|
setContentDefaultHeight()
|
||||||
// mBinding.rlvChats.smoothScrollToPosition(itemCount - 1)
|
}
|
||||||
// } else {
|
}
|
||||||
// hideSoftKeyboard()
|
}
|
||||||
// }
|
chatPageViewModel!!.showEmojiLayout.observe(this) {
|
||||||
// }
|
if (it) {
|
||||||
// mBinding.rlContent.setOnClickListener {
|
hideSoftKeyboard()//隐藏软键盘
|
||||||
// Log.e("ChatActivity", "bindView: 点击")
|
setContentLayoutHeight()
|
||||||
// chatPageViewModel!!.showChooseLayout.value = false
|
} else {
|
||||||
// chatPageViewModel!!.showEmojiLayout.value = false
|
val isShow =
|
||||||
// chatPageViewModel!!.showReplyLayout.value = false
|
chatPageViewModel!!.showReplyLayout.value!! || chatPageViewModel!!.showChooseLayout.value!!
|
||||||
// hideSoftKeyboard()
|
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.setTextSize(14F, isSp = true)
|
||||||
mBinding.wvView.setAutoFitTextSize(true)
|
mBinding.wvView.setAutoFitTextSize(true)
|
||||||
mBinding.wvView.setOnItemSelectedListener(object : WheelView.OnItemSelectedListener {
|
mBinding.wvView.setOnItemSelectedListener(object : WheelView.OnItemSelectedListener {
|
||||||
@ -91,6 +124,7 @@ class ChatActivity : BaseActivity() {
|
|||||||
mBinding.etMsg.setText(data.toString())
|
mBinding.etMsg.setText(data.toString())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
chatPageViewModel!!.chooseType.observe(this) {
|
chatPageViewModel!!.chooseType.observe(this) {
|
||||||
when (it) {
|
when (it) {
|
||||||
PickerType.TYPE_PIC -> {
|
PickerType.TYPE_PIC -> {
|
||||||
@ -121,7 +155,7 @@ class ChatActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
chatPageViewModel!!.scrollListToBottom.observe(this) {
|
chatPageViewModel!!.scrollListToBottom.observe(this) {
|
||||||
Log.e("TAG", "bindView:滚动 ${it} ")
|
Log.e("TAG", "bindView:滚动 $it ")
|
||||||
if (it) {
|
if (it) {
|
||||||
val layoutManager = mBinding.rlvChats.layoutManager as LinearLayoutManager
|
val layoutManager = mBinding.rlvChats.layoutManager as LinearLayoutManager
|
||||||
val itemCount = layoutManager.itemCount
|
val itemCount = layoutManager.itemCount
|
||||||
@ -136,14 +170,24 @@ class ChatActivity : BaseActivity() {
|
|||||||
chatPageViewModel!!.scrollListToBottom.value = false
|
chatPageViewModel!!.scrollListToBottom.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mBinding.llBottomLayout.visibility = View.VISIBLE
|
|
||||||
mBinding.rlBottom.visibility = View.GONE
|
mBinding.rlBottom.visibility = View.GONE
|
||||||
mBinding.rlvChats.viewTreeObserver.addOnGlobalLayoutListener {
|
mBinding.rlvChats.viewTreeObserver.addOnGlobalLayoutListener {
|
||||||
mContentHeight = mBinding.rlvChats.height
|
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,
|
SoftKeyBoardListener().setChangeListener(this@ChatActivity,
|
||||||
{ h ->
|
{ 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
|
mBinding.rlBottom.visibility = View.VISIBLE
|
||||||
//重置layout高度
|
//重置layout高度
|
||||||
val layoutParams = mBinding.rlvChats.layoutParams
|
val layoutParams = mBinding.rlvChats.layoutParams
|
||||||
@ -158,16 +202,17 @@ class ChatActivity : BaseActivity() {
|
|||||||
0
|
0
|
||||||
)
|
)
|
||||||
}, 100)
|
}, 100)
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
{ _ ->
|
{ _ ->
|
||||||
val layoutParams = mBinding.rlvChats.layoutParams
|
Log.e("ChatActivity", "软键盘: 隐藏")
|
||||||
layoutParams.height = mContentHeight
|
val isShowOther =
|
||||||
mBinding.rlvChats.layoutParams = layoutParams
|
chatPageViewModel!!.showReplyLayout.value!! || chatPageViewModel!!.showEmojiLayout.value!! || chatPageViewModel!!.showChooseLayout.value!!
|
||||||
mBinding.llBottomLayout.visibility = View.VISIBLE
|
if (!isShowOther) {
|
||||||
mBinding.rlBottom.visibility = View.GONE
|
val layoutParams = mBinding.rlvChats.layoutParams
|
||||||
|
layoutParams.height = mContentHeight
|
||||||
|
mBinding.rlvChats.layoutParams = layoutParams
|
||||||
|
mBinding.rlBottom.visibility = View.GONE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
registerLocalReceiver()
|
registerLocalReceiver()
|
||||||
}
|
}
|
||||||
@ -185,6 +230,31 @@ class ChatActivity : BaseActivity() {
|
|||||||
unregisterReceiver(mLocalReceiver)
|
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() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
unRegisterLocalReceiver()
|
unRegisterLocalReceiver()
|
||||||
@ -195,12 +265,17 @@ class ChatActivity : BaseActivity() {
|
|||||||
when (intent?.action) {
|
when (intent?.action) {
|
||||||
ProjectConfig.A_S_MSG_RECEIVER -> {
|
ProjectConfig.A_S_MSG_RECEIVER -> {
|
||||||
val msg = intent.getStringExtra("msg")
|
val msg = intent.getStringExtra("msg")
|
||||||
Log.e("LocalReceiver", "onReceive: ${msg}")
|
Log.e("LocalReceiver", "onReceive: $msg")
|
||||||
chatPageViewModel!!.receiveMsg(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
|
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||||
|
|
||||||
class LoginActivity : BaseActivity() {
|
class LoginActivity : BaseActivity() {
|
||||||
private lateinit var mBinding: ActivityLoginBinding;
|
private lateinit var mBinding: ActivityLoginBinding
|
||||||
private var mLoading: LoadingDialog? = null;
|
private var mLoading: LoadingDialog? = null
|
||||||
private val loginPageViewModel: LoginPageViewModel by lazy {
|
private val loginPageViewModel: LoginPageViewModel by lazy {
|
||||||
ViewModelProvider(this)[LoginPageViewModel::class.java]
|
ViewModelProvider(this)[LoginPageViewModel::class.java]
|
||||||
}
|
}
|
||||||
@ -40,13 +40,13 @@ class LoginActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
loginPageViewModel.isLoginSuccess.observe(this) {
|
loginPageViewModel.isLoginSuccess.observe(this) {
|
||||||
if (it) {
|
if (it) {
|
||||||
// startActivity(Intent(this@LoginActivity, MainActivity::class.java))
|
startActivity(Intent(this@LoginActivity, MainActivity::class.java))
|
||||||
startActivity(
|
// startActivity(
|
||||||
Intent(
|
// Intent(
|
||||||
this@LoginActivity,
|
// this@LoginActivity,
|
||||||
ChatActivity::class.java
|
// ChatActivity::class.java
|
||||||
).putExtra("fromId", "2")
|
// ).putExtra("fromId", "2").putExtra("name", "测试")
|
||||||
)
|
// )
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ class MainActivity : BaseActivity() {
|
|||||||
return@setOnItemSelectedListener true;
|
return@setOnItemSelectedListener true;
|
||||||
}//我的
|
}//我的
|
||||||
}
|
}
|
||||||
false;
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
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.services.SocketService
|
||||||
import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel
|
import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel
|
||||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||||
|
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||||
|
|
||||||
class MsgFragment : Fragment(), MsgViewModel.OnItemClickListener,
|
class MsgFragment : Fragment(), AdapterItemClickListener<MsgCategoryBean>,
|
||||||
MainActivity.OnSocketConnectListener {
|
MainActivity.OnSocketConnectListener {
|
||||||
private lateinit var mMsgBinding: FragmentMsgBinding
|
private lateinit var mMsgBinding: FragmentMsgBinding
|
||||||
private var mActivity: MainActivity? = null
|
private var mActivity: MainActivity? = null
|
||||||
|
@ -59,6 +59,7 @@ class SocketService : Service(), WsManager.MsgCallBack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
||||||
private fun registerLocalReceiver() {
|
private fun registerLocalReceiver() {
|
||||||
val intentFilter = IntentFilter()
|
val intentFilter = IntentFilter()
|
||||||
mLocalReceiver = LocalReceiver()
|
mLocalReceiver = LocalReceiver()
|
||||||
|
@ -2,6 +2,9 @@ package com.tenlionsoft.aimz_k.viewmodel
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.os.Message
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.lifecycle.MutableLiveData
|
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.BodyContent
|
||||||
import com.tenlionsoft.aimz_k.model.CoverSealedBean
|
import com.tenlionsoft.aimz_k.model.CoverSealedBean
|
||||||
import com.tenlionsoft.aimz_k.model.DbManager
|
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.MsgBean
|
||||||
import com.tenlionsoft.aimz_k.model.MsgConvertBean
|
import com.tenlionsoft.aimz_k.model.MsgConvertBean
|
||||||
import com.tenlionsoft.aimz_k.model.PickerType
|
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.aimz_k.net.UserApi
|
||||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||||
|
import com.tenlionsoft.baselib.net.ExParse
|
||||||
import com.tenlionsoft.baselib.net.RetrofitClient
|
import com.tenlionsoft.baselib.net.RetrofitClient
|
||||||
import com.tenlionsoft.baselib.utils.SpUtils
|
import com.tenlionsoft.baselib.utils.SpUtils
|
||||||
import com.tenlionsoft.baselib.utils.TimeUtils
|
import com.tenlionsoft.baselib.utils.TimeUtils
|
||||||
|
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -34,7 +40,6 @@ import okhttp3.MultipartBody
|
|||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.RequestBody.Companion.asRequestBody
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
|
|
||||||
|
|
||||||
class ChatPageViewModel(
|
class ChatPageViewModel(
|
||||||
private val fromId: String,
|
private val fromId: String,
|
||||||
private val toId: String,
|
private val toId: String,
|
||||||
@ -51,7 +56,34 @@ class ChatPageViewModel(
|
|||||||
private val retrofitClient = RetrofitClient.getInstance(context)
|
private val retrofitClient = RetrofitClient.getInstance(context)
|
||||||
private val netApi = retrofitClient.create(UserApi::class.java)
|
private val netApi = retrofitClient.create(UserApi::class.java)
|
||||||
var adapter: ChatMsgAdapter = ChatMsgAdapter(_msgList.value ?: emptyList(), this)
|
var adapter: ChatMsgAdapter = ChatMsgAdapter(_msgList.value ?: emptyList(), this)
|
||||||
|
var onItemClickListener: AdapterItemClickListener<MsgBean>? = null
|
||||||
private val mGson: Gson = Gson()
|
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 {
|
init {
|
||||||
Log.e("ChatPageViewModel", "Init: ${showSendBtn.value}")
|
Log.e("ChatPageViewModel", "Init: ${showSendBtn.value}")
|
||||||
@ -78,20 +110,18 @@ class ChatPageViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onShowReplyLayout() {
|
fun onShowReplyLayout() {
|
||||||
showReplyLayout.value = !showReplyLayout.value!!
|
|
||||||
showEmojiLayout.value = false
|
showEmojiLayout.value = false
|
||||||
showChooseLayout.value = false
|
showChooseLayout.value = false
|
||||||
showSoftKeyboard.value = !showReplyLayout.value!!
|
showReplyLayout.value = !showReplyLayout.value!!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换emoji layout
|
* 切换emoji layout
|
||||||
*/
|
*/
|
||||||
fun onShowEmojiLayout() {
|
fun onShowEmojiLayout() {
|
||||||
showEmojiLayout.value = !showEmojiLayout.value!!
|
|
||||||
showChooseLayout.value = false
|
showChooseLayout.value = false
|
||||||
showReplyLayout.value = false
|
showReplyLayout.value = false
|
||||||
showSoftKeyboard.value = !showEmojiLayout.value!!
|
showEmojiLayout.value = !showEmojiLayout.value!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,10 +129,9 @@ class ChatPageViewModel(
|
|||||||
* 切换选择layout
|
* 切换选择layout
|
||||||
*/
|
*/
|
||||||
fun onShowChooseLayout() {
|
fun onShowChooseLayout() {
|
||||||
showChooseLayout.value = !showChooseLayout.value!!
|
|
||||||
showEmojiLayout.value = false
|
showEmojiLayout.value = false
|
||||||
showReplyLayout.value = false
|
showReplyLayout.value = false
|
||||||
showSoftKeyboard.value = !showChooseLayout.value!!
|
showChooseLayout.value = !showChooseLayout.value!!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,11 +163,83 @@ class ChatPageViewModel(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
viewModelScope.launch {
|
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 {
|
try {
|
||||||
for (item in list) {
|
for (item in list) {
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
@ -146,7 +247,7 @@ class ChatPageViewModel(
|
|||||||
item.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
item.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||||
val body: MultipartBody.Part =
|
val body: MultipartBody.Part =
|
||||||
MultipartBody.Part.createFormData(
|
MultipartBody.Part.createFormData(
|
||||||
"audio",
|
"image",
|
||||||
item.file!!.getName(),
|
item.file!!.getName(),
|
||||||
requestFile
|
requestFile
|
||||||
)
|
)
|
||||||
@ -154,35 +255,40 @@ class ChatPageViewModel(
|
|||||||
val bean = retrofitClient.makeApiCall {
|
val bean = retrofitClient.makeApiCall {
|
||||||
netApi.doUploadImage(body)
|
netApi.doUploadImage(body)
|
||||||
}
|
}
|
||||||
|
Log.e("ChatPageViewModel", "doUploadImgs: $bean")
|
||||||
if (bean.code == 200) {
|
if (bean.code == 200) {
|
||||||
//上传成功
|
//上传成功
|
||||||
//TODO 构建消息实体
|
sendMedia(ProjectConfig.MSG_IMG, bean.data)
|
||||||
//TODO 发送消息
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
//TODO 上传失败
|
|
||||||
}
|
}
|
||||||
|
++count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (count == list.size) {
|
||||||
|
showLoadDialog.value = false
|
||||||
|
count = 1
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
showLoadDialog.value = false
|
||||||
|
count = 1
|
||||||
|
ExParse.parse(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//发送 图片/视频/音频/文件
|
||||||
* 上传视频
|
private fun sendMedia(type: String, data: FileDataBean) {
|
||||||
*/
|
val intent = Intent(ProjectConfig.A_S_MSG_SEND)
|
||||||
fun uploadVideo(meta: VideoMeta) {
|
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() {
|
private fun refresh() {
|
||||||
@ -198,6 +304,7 @@ class ChatPageViewModel(
|
|||||||
_msgList.value = _msgList.value?.plus(msgBean)
|
_msgList.value = _msgList.value?.plus(msgBean)
|
||||||
adapter.setData(_msgList.value!!)
|
adapter.setData(_msgList.value!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送文本信息
|
* 发送文本信息
|
||||||
*/
|
*/
|
||||||
@ -210,6 +317,10 @@ class ChatPageViewModel(
|
|||||||
_msgList.value = _msgList.value?.plus(msgBean)
|
_msgList.value = _msgList.value?.plus(msgBean)
|
||||||
adapter.setData(_msgList.value!!)
|
adapter.setData(_msgList.value!!)
|
||||||
}
|
}
|
||||||
|
// 保存发送信息到消息队列
|
||||||
|
//添加到消息队列
|
||||||
|
|
||||||
|
sendHandlerToLooper(b)
|
||||||
intent.putExtra("msgBean", b)
|
intent.putExtra("msgBean", b)
|
||||||
v.context.sendBroadcast(intent)
|
v.context.sendBroadcast(intent)
|
||||||
txtMsg.value = ""
|
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?) {
|
fun receiveMsg(msg: String?) {
|
||||||
if (!msg.isNullOrEmpty()) {
|
if (!msg.isNullOrEmpty()) {
|
||||||
val bean = ConvertBeanUtils.covertBean(msg)
|
when (val bean = ConvertBeanUtils.covertBean(msg)) {
|
||||||
when (bean) {
|
|
||||||
//消息状态
|
//消息状态
|
||||||
is CoverSealedBean.StateBean -> {
|
is CoverSealedBean.StateBean -> {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@ -244,6 +362,9 @@ class ChatPageViewModel(
|
|||||||
dao.updateStatus(bean.data.messageId, statusType)
|
dao.updateStatus(bean.data.messageId, statusType)
|
||||||
cDao.updateStatus(bean.data.sender.senderId!!, statusType)
|
cDao.updateStatus(bean.data.sender.senderId!!, statusType)
|
||||||
}
|
}
|
||||||
|
//删除队列里面的Bean
|
||||||
|
msgHandlerList.removeIf { it.messageId == bean.data.messageId }
|
||||||
|
handler.removeMessages(bean.data.timestamp.toInt())
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +396,7 @@ class ChatPageViewModel(
|
|||||||
context.sendBroadcast(intent)
|
context.sendBroadcast(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
//构建发送实体
|
//构建文字发送实体
|
||||||
private fun buildSendBean(type: String): MsgConvertBean {
|
private fun buildSendBean(type: String): MsgConvertBean {
|
||||||
val bodyBean = BodyContent(content = txtMsg.value, null, null)
|
val bodyBean = BodyContent(content = txtMsg.value, null, null)
|
||||||
val body = mGson.toJson(bodyBean)
|
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 {
|
private fun buildStatusBean(messageId: String): MsgConvertBean {
|
||||||
val bodyBean = BodyContent(content = null, msg = "", statusType = "SUCCESS_RECEIVED")
|
val bodyBean = BodyContent(content = null, msg = "", statusType = "SUCCESS_RECEIVED")
|
||||||
@ -320,4 +466,7 @@ class ChatPageViewModel(
|
|||||||
status = "",
|
status = "",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class LoginPageViewModel : BaseViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun doLogin() {
|
fun doLogin() {
|
||||||
isLoginSuccess.value = true
|
// isLoginSuccess.value= true
|
||||||
val isLegal = checkParams();
|
val isLegal = checkParams();
|
||||||
if (isLegal) {
|
if (isLegal) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
@ -19,6 +19,7 @@ import com.tenlionsoft.aimz_k.model.Sender
|
|||||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||||
import com.tenlionsoft.baselib.utils.SpUtils
|
import com.tenlionsoft.baselib.utils.SpUtils
|
||||||
import com.tenlionsoft.baselib.utils.TimeUtils
|
import com.tenlionsoft.baselib.utils.TimeUtils
|
||||||
|
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -26,7 +27,7 @@ import kotlinx.coroutines.withContext
|
|||||||
class MsgViewModel : ViewModel() {
|
class MsgViewModel : ViewModel() {
|
||||||
private val _pwdList = MutableLiveData<List<MsgCategoryBean>>()
|
private val _pwdList = MutableLiveData<List<MsgCategoryBean>>()
|
||||||
var adapter: CategoryAdapter = CategoryAdapter(_pwdList.value ?: emptyList(), this)
|
var adapter: CategoryAdapter = CategoryAdapter(_pwdList.value ?: emptyList(), this)
|
||||||
var onItemClickListener: OnItemClickListener? = null
|
var onItemClickListener: AdapterItemClickListener<MsgCategoryBean>? = null
|
||||||
val isLogining = MutableLiveData(false)
|
val isLogining = MutableLiveData(false)
|
||||||
private val mGson = Gson()
|
private val mGson = Gson()
|
||||||
private var mCurrentPage: Int = 1
|
private var mCurrentPage: Int = 1
|
||||||
@ -156,8 +157,4 @@ class MsgViewModel : ViewModel() {
|
|||||||
fun refresh() {
|
fun refresh() {
|
||||||
getList(true)
|
getList(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OnItemClickListener {
|
|
||||||
fun onItemClick(msgCategoryBean: MsgCategoryBean)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package com.tenlionsoft.aimz_k.widget
|
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.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
@ -10,11 +13,18 @@ import androidx.recyclerview.widget.RecyclerView.Adapter
|
|||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.bumptech.glide.request.RequestOptions
|
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.google.gson.Gson
|
||||||
import com.tenlionsoft.aimz_k.R
|
import com.tenlionsoft.aimz_k.R
|
||||||
import com.tenlionsoft.aimz_k.model.BodyContent
|
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.contacts.ProjectConfig
|
||||||
|
import com.tenlionsoft.baselib.model.ImageSize
|
||||||
|
import com.tenlionsoft.baselib.utils.ImageUtils
|
||||||
import com.tenlionsoft.baselib.utils.TimeUtils
|
import com.tenlionsoft.baselib.utils.TimeUtils
|
||||||
|
import com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
||||||
|
|
||||||
|
|
||||||
object BindingUtils {
|
object BindingUtils {
|
||||||
@ -61,7 +71,131 @@ object BindingUtils {
|
|||||||
} else {
|
} else {
|
||||||
val gson = Gson()
|
val gson = Gson()
|
||||||
val body = gson.fromJson(str, BodyContent::class.java)
|
val body = gson.fromJson(str, BodyContent::class.java)
|
||||||
tv.text = body.content
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@color/green"
|
|
||||||
tools:listitem="@layout/item_msg_my" />
|
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">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="pos"
|
name="pos"
|
||||||
type="Integer" />
|
type="Integer" />
|
||||||
@ -11,6 +12,7 @@
|
|||||||
<variable
|
<variable
|
||||||
name="bean"
|
name="bean"
|
||||||
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="state"
|
name="state"
|
||||||
type="String" />
|
type="String" />
|
||||||
@ -41,19 +43,19 @@
|
|||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/pb_sending"
|
android:id="@+id/pb_sending"
|
||||||
|
isShowLoading="@{state}"
|
||||||
android:layout_width="15dp"
|
android:layout_width="15dp"
|
||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
isShowLoading="@{state}"
|
|
||||||
android:indeterminateBehavior="repeat"
|
android:indeterminateBehavior="repeat"
|
||||||
android:indeterminateDrawable="@drawable/anim_loading" />
|
android:indeterminateDrawable="@drawable/anim_loading" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_msg_state_fail"
|
android:id="@+id/iv_msg_state_fail"
|
||||||
|
isShowFail="@{state}"
|
||||||
android:layout_width="15dp"
|
android:layout_width="15dp"
|
||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
isShowFail="@{state}"
|
|
||||||
android:src="@drawable/msg_state_fail_resend"
|
android:src="@drawable/msg_state_fail_resend"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
@ -68,6 +70,7 @@
|
|||||||
|
|
||||||
<com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
<com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
||||||
android:id="@+id/iv_content"
|
android:id="@+id/iv_content"
|
||||||
|
jsonConvertMsgImgBody="@{bean.body}"
|
||||||
android:layout_width="100dp"
|
android:layout_width="100dp"
|
||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="pos"
|
name="pos"
|
||||||
type="Integer" />
|
type="Integer" />
|
||||||
@ -11,6 +12,7 @@
|
|||||||
<variable
|
<variable
|
||||||
name="bean"
|
name="bean"
|
||||||
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
type="com.tenlionsoft.aimz_k.model.MsgBean" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="state"
|
name="state"
|
||||||
type="String" />>
|
type="String" />>
|
||||||
@ -41,18 +43,18 @@
|
|||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/pb_sending"
|
android:id="@+id/pb_sending"
|
||||||
|
isShowLoading="@{state}"
|
||||||
android:layout_width="15dp"
|
android:layout_width="15dp"
|
||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
isShowLoading="@{state}"
|
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:indeterminateBehavior="repeat"
|
android:indeterminateBehavior="repeat"
|
||||||
android:indeterminateDrawable="@drawable/anim_loading" />
|
android:indeterminateDrawable="@drawable/anim_loading" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_msg_state_fail"
|
android:id="@+id/iv_msg_state_fail"
|
||||||
|
isShowFail="@{state}"
|
||||||
android:layout_width="15dp"
|
android:layout_width="15dp"
|
||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
isShowFail="@{state}"
|
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:src="@drawable/msg_state_fail_resend"
|
android:src="@drawable/msg_state_fail_resend"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
@ -68,8 +70,9 @@
|
|||||||
|
|
||||||
<com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
<com.tenlionsoft.baselib.widget.chat.BubbleImageView
|
||||||
android:id="@+id/iv_content"
|
android:id="@+id/iv_content"
|
||||||
android:layout_width="100dp"
|
jsonConvertMsgAudioImg="@{bean.body}"
|
||||||
android:layout_height="100dp"
|
android:layout_width="120dp"
|
||||||
|
android:layout_height="120dp"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_marginStart="0dp"
|
android:layout_marginStart="0dp"
|
||||||
android:adjustViewBounds="true"
|
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:layout_marginStart="0dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
jsonConvertMsgImgBody="@{bean.body}"
|
||||||
android:transitionName="sharedView"
|
android:transitionName="sharedView"
|
||||||
app:angle="6dp"
|
app:angle="6dp"
|
||||||
app:arrowHeight="8dp"
|
app:arrowHeight="8dp"
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
android:layout_width="100dp"
|
android:layout_width="100dp"
|
||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
jsonConvertMsgAudioImg="@{bean.body}"
|
||||||
android:layout_marginStart="0dp"
|
android:layout_marginStart="0dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
@ -19,8 +19,9 @@ object ProjectConfig {
|
|||||||
//消息类型
|
//消息类型
|
||||||
const val MSG_TEXT = "MSG_TEXT"
|
const val MSG_TEXT = "MSG_TEXT"
|
||||||
const val MSG_FILE = "MSG_FILE"
|
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_VIDEO = "MSG_VIDEO"
|
||||||
|
const val MSG_AUDIO = "MSG_AUDIO"
|
||||||
const val MSG_STATUS = "STATUS" //状态消息
|
const val MSG_STATUS = "STATUS" //状态消息
|
||||||
const val MSG_SEND_ING: String = "PENDING"//11 //发送中
|
const val MSG_SEND_ING: String = "PENDING"//11 //发送中
|
||||||
const val MSG_SEND_FAIL: String = "ERROR"//12 //发送失败
|
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
|
package com.tenlionsoft.baselib.net
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.tenlionsoft.baselib.contacts.NetConfig
|
import com.tenlionsoft.baselib.contacts.NetConfig
|
||||||
import com.tenlionsoft.baselib.utils.SpUtils
|
import com.tenlionsoft.baselib.utils.SpUtils
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
@ -19,7 +20,10 @@ class BaseUrlInterceptor : Interceptor {
|
|||||||
val oldHttpUrl = request.url;
|
val oldHttpUrl = request.url;
|
||||||
val headers = request.headers("project");
|
val headers = request.headers("project");
|
||||||
//公共Token header
|
//公共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.removeHeader("token")
|
||||||
builder.addHeader("X-WG-TOKEN", SpUtils.getToken())
|
builder.addHeader("X-WG-TOKEN", SpUtils.getToken())
|
||||||
builder.addHeader("X-WG-TYPE", "APP")
|
builder.addHeader("X-WG-TYPE", "APP")
|
||||||
@ -43,7 +47,7 @@ class BaseUrlInterceptor : Interceptor {
|
|||||||
.build();
|
.build();
|
||||||
return chain.proceed(builder.url(newFullUrl).build());
|
return chain.proceed(builder.url(newFullUrl).build());
|
||||||
} else {
|
} 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 |