diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/adapter/ChatMsgAdapter.kt b/app/src/main/java/com/tenlionsoft/aimz_k/adapter/ChatMsgAdapter.kt index 1a6823c..5315d95 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/adapter/ChatMsgAdapter.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/adapter/ChatMsgAdapter.kt @@ -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, viewModel: ChatPageViewModel) : +class ChatMsgAdapter(datas: List, val viewModel: ChatPageViewModel) : BaseBindingAdapter(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, viewModel: ChatPageViewModel) : override fun bindItem(holder: BaseViewHolder, 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, 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, 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") diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/model/FileUploadStateBean.kt b/app/src/main/java/com/tenlionsoft/aimz_k/model/FileUploadStateBean.kt new file mode 100644 index 0000000..c057fc8 --- /dev/null +++ b/app/src/main/java/com/tenlionsoft/aimz_k/model/FileUploadStateBean.kt @@ -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 +) diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/net/UserApi.kt b/app/src/main/java/com/tenlionsoft/aimz_k/net/UserApi.kt index fa45e40..ee6ed5b 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/net/UserApi.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/net/UserApi.kt @@ -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 } \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt index db2a179..fb559c3 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/ChatActivity.kt @@ -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 { 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 create(modelClass: Class): 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) - - }, { _ -> - val layoutParams = mBinding.rlvChats.layoutParams - layoutParams.height = mContentHeight - mBinding.rlvChats.layoutParams = layoutParams - mBinding.llBottomLayout.visibility = View.VISIBLE - mBinding.rlBottom.visibility = View.GONE - + 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.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) { + + } } diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/LoginActivity.kt b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/LoginActivity.kt index aafe554..365b938 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/LoginActivity.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/LoginActivity.kt @@ -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() } } diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/MainActivity.kt b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/MainActivity.kt index 1a124f0..fd1b023 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/MainActivity.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/page/activity/MainActivity.kt @@ -90,7 +90,7 @@ class MainActivity : BaseActivity() { return@setOnItemSelectedListener true; }//我的 } - false; + false } onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt b/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt index 4305faf..3156f64 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/page/fragments/MsgFragment.kt @@ -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, MainActivity.OnSocketConnectListener { private lateinit var mMsgBinding: FragmentMsgBinding private var mActivity: MainActivity? = null diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/services/SocketService.kt b/app/src/main/java/com/tenlionsoft/aimz_k/services/SocketService.kt index c2acbe7..414de22 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/services/SocketService.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/services/SocketService.kt @@ -59,6 +59,7 @@ class SocketService : Service(), WsManager.MsgCallBack { } + @SuppressLint("UnspecifiedRegisterReceiverFlag") private fun registerLocalReceiver() { val intentFilter = IntentFilter() mLocalReceiver = LocalReceiver() diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt index 311a6d4..5decb01 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/ChatPageViewModel.kt @@ -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? = null private val mGson: Gson = Gson() + private var msgHandlerList: ArrayList = 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) { + + /** + * 上传视频 + */ + 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) { 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 = "", ) } -} \ No newline at end of file + +} + + diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt index 6b1eb5f..ca5b097 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/LoginPageViewModel.kt @@ -37,7 +37,7 @@ class LoginPageViewModel : BaseViewModel() { } fun doLogin() { - isLoginSuccess.value = true +// isLoginSuccess.value= true val isLegal = checkParams(); if (isLegal) { viewModelScope.launch { diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt index 3280248..94158fe 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/viewmodel/MsgViewModel.kt @@ -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>() var adapter: CategoryAdapter = CategoryAdapter(_pwdList.value ?: emptyList(), this) - var onItemClickListener: OnItemClickListener? = null + var onItemClickListener: AdapterItemClickListener? = 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) - } } \ No newline at end of file diff --git a/app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt b/app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt index 7d14e58..5403e1a 100644 --- a/app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt +++ b/app/src/main/java/com/tenlionsoft/aimz_k/widget/BindingUtils.kt @@ -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,7 +71,131 @@ object BindingUtils { } else { val gson = Gson() 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(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() { + override fun onResourceReady( + resource: Drawable, + transition: Transition? + ) { + 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) } } diff --git a/app/src/main/res/drawable-xhdpi/ic_audio.png b/app/src/main/res/drawable-xhdpi/ic_audio.png new file mode 100644 index 0000000..a3a4f5f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_audio.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_excel.png b/app/src/main/res/drawable-xhdpi/ic_excel.png new file mode 100644 index 0000000..84eeeaa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_excel.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_file.png b/app/src/main/res/drawable-xhdpi/ic_file.png new file mode 100644 index 0000000..e328a15 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_file.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_image.png b/app/src/main/res/drawable-xhdpi/ic_image.png new file mode 100644 index 0000000..0e14285 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_image.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_mp.png b/app/src/main/res/drawable-xhdpi/ic_mp.png new file mode 100644 index 0000000..f7bb064 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_mp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_pdf.png b/app/src/main/res/drawable-xhdpi/ic_pdf.png new file mode 100644 index 0000000..8b36bb4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_pdf.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_ppt.png b/app/src/main/res/drawable-xhdpi/ic_ppt.png new file mode 100644 index 0000000..0586719 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_ppt.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_psd.png b/app/src/main/res/drawable-xhdpi/ic_psd.png new file mode 100644 index 0000000..46ce262 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_psd.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_word.png b/app/src/main/res/drawable-xhdpi/ic_word.png new file mode 100644 index 0000000..c097715 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_word.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_zip.png b/app/src/main/res/drawable-xhdpi/ic_zip.png new file mode 100644 index 0000000..325dbcd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_zip.png differ diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml index 4113ebf..202dcdc 100644 --- a/app/src/main/res/layout/activity_chat.xml +++ b/app/src/main/res/layout/activity_chat.xml @@ -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" /> diff --git a/app/src/main/res/layout/item_msg_my_file.xml b/app/src/main/res/layout/item_msg_my_file.xml new file mode 100644 index 0000000..fc9348a --- /dev/null +++ b/app/src/main/res/layout/item_msg_my_file.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_msg_my_img.xml b/app/src/main/res/layout/item_msg_my_img.xml index b140e3f..cd001e7 100644 --- a/app/src/main/res/layout/item_msg_my_img.xml +++ b/app/src/main/res/layout/item_msg_my_img.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools"> + @@ -11,6 +12,7 @@ + @@ -41,19 +43,19 @@ @@ -68,6 +70,7 @@ + @@ -11,6 +12,7 @@ + > @@ -41,18 +43,18 @@ @@ -68,8 +70,9 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_msg_other_img.xml b/app/src/main/res/layout/item_msg_other_img.xml index 5b85c45..34472df 100644 --- a/app/src/main/res/layout/item_msg_other_img.xml +++ b/app/src/main/res/layout/item_msg_other_img.xml @@ -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" diff --git a/app/src/main/res/layout/item_msg_other_video.xml b/app/src/main/res/layout/item_msg_other_video.xml index 504a9d3..05a671c 100644 --- a/app/src/main/res/layout/item_msg_other_video.xml +++ b/app/src/main/res/layout/item_msg_other_video.xml @@ -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" diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/contacts/ProjectConfig.kt b/baselib/src/main/java/com/tenlionsoft/baselib/contacts/ProjectConfig.kt index fffd18b..5fd148c 100644 --- a/baselib/src/main/java/com/tenlionsoft/baselib/contacts/ProjectConfig.kt +++ b/baselib/src/main/java/com/tenlionsoft/baselib/contacts/ProjectConfig.kt @@ -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 //发送失败 diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/model/ImageSize.kt b/baselib/src/main/java/com/tenlionsoft/baselib/model/ImageSize.kt new file mode 100644 index 0000000..a21fae4 --- /dev/null +++ b/baselib/src/main/java/com/tenlionsoft/baselib/model/ImageSize.kt @@ -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 + } +} \ No newline at end of file diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/net/BaseUrlInterceptor.kt b/baselib/src/main/java/com/tenlionsoft/baselib/net/BaseUrlInterceptor.kt index 8dd68f8..cb331e0 100644 --- a/baselib/src/main/java/com/tenlionsoft/baselib/net/BaseUrlInterceptor.kt +++ b/baselib/src/main/java/com/tenlionsoft/baselib/net/BaseUrlInterceptor.kt @@ -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()); } } } \ No newline at end of file diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/utils/ImageUtils.kt b/baselib/src/main/java/com/tenlionsoft/baselib/utils/ImageUtils.kt new file mode 100644 index 0000000..8a614eb --- /dev/null +++ b/baselib/src/main/java/com/tenlionsoft/baselib/utils/ImageUtils.kt @@ -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 + } +} \ No newline at end of file diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/widget/AdapterItemClickListener.kt b/baselib/src/main/java/com/tenlionsoft/baselib/widget/AdapterItemClickListener.kt new file mode 100644 index 0000000..842c268 --- /dev/null +++ b/baselib/src/main/java/com/tenlionsoft/baselib/widget/AdapterItemClickListener.kt @@ -0,0 +1,5 @@ +package com.tenlionsoft.baselib.widget + +interface AdapterItemClickListener { + fun onItemClick(data: D) +} \ No newline at end of file diff --git a/baselib/src/main/res/drawable-xhdpi/ic_img_load_err.png b/baselib/src/main/res/drawable-xhdpi/ic_img_load_err.png new file mode 100644 index 0000000..2f04368 Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_img_load_err.png differ