增加没有数据的提示页面

修改user数据的使用
This commit is contained in:
squallzhjch
2023-01-09 14:54:00 +08:00
parent 1e52eac92c
commit 0bf8114dc5
12 changed files with 241 additions and 109 deletions

View File

@@ -1,6 +1,7 @@
package com.navinfo.volvo.repository.preferences package com.navinfo.volvo.repository.preferences
import com.navinfo.volvo.model.proto.LoginUser import com.navinfo.volvo.model.proto.LoginUser
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
/** /**

View File

@@ -7,9 +7,12 @@ import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore import androidx.datastore.preferences.preferencesDataStore
import androidx.lifecycle.viewModelScope
import com.navinfo.volvo.model.proto.LoginUser import com.navinfo.volvo.model.proto.LoginUser
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject

View File

@@ -35,6 +35,7 @@ class HomeAdapter(fragment: Fragment) :
holder.onBind(position) holder.onBind(position)
} }
fun getItemData(position: Int): GreetingMessage { fun getItemData(position: Int): GreetingMessage {
return getItem(position)!! return getItem(position)!!
} }

View File

@@ -14,6 +14,8 @@ import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.navinfo.volvo.R import com.navinfo.volvo.R
import com.navinfo.volvo.databinding.FragmentHomeBinding import com.navinfo.volvo.databinding.FragmentHomeBinding
import com.navinfo.volvo.databinding.HomeAdapterNotingBinding
import com.navinfo.volvo.databinding.LoadStateViewBinding
import com.navinfo.volvo.tools.DisplayUtil import com.navinfo.volvo.tools.DisplayUtil
import com.navinfo.volvo.ui.fragments.BaseFragment import com.navinfo.volvo.ui.fragments.BaseFragment
import com.yanzhenjie.recyclerview.* import com.yanzhenjie.recyclerview.*
@@ -33,12 +35,14 @@ class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListene
private val viewModel by viewModels<HomeViewModel>() private val viewModel by viewModels<HomeViewModel>()
private val messageAdapter by lazy { HomeAdapter(this) } private val messageAdapter by lazy { HomeAdapter(this) }
private var headBinding: HomeAdapterNotingBinding? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View { ): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false) _binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root
headBinding = HomeAdapterNotingBinding.inflate(inflater, container, false)
initView() initView()
return root return root
} }
@@ -95,6 +99,7 @@ class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListene
binding.homeRecyclerview.setOnItemClickListener(this) binding.homeRecyclerview.setOnItemClickListener(this)
//使用下拉加载 //使用下拉加载
// binding.homeRecyclerview.useDefaultLoadMore() // 使用默认的加载更多的View。 // binding.homeRecyclerview.useDefaultLoadMore() // 使用默认的加载更多的View。
binding.homeRecyclerview.setLoadMoreListener { binding.homeRecyclerview.setLoadMoreListener {
Log.e("jingo", "下拉加载开始") Log.e("jingo", "下拉加载开始")
@@ -118,9 +123,11 @@ class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListene
messageAdapter.addLoadStateListener { messageAdapter.addLoadStateListener {
when (it.refresh) { when (it.refresh) {
is LoadState.NotLoading -> { is LoadState.NotLoading -> {
binding.homeRecyclerview.addHeaderView(headBinding!!.root)
Log.d("jingo", "is NotLoading") Log.d("jingo", "is NotLoading")
} }
is LoadState.Loading -> { is LoadState.Loading -> {
binding.homeRecyclerview.removeHeaderView(headBinding!!.root)
Log.d("jingo", "is Loading") Log.d("jingo", "is Loading")
} }
is LoadState.Error -> { is LoadState.Error -> {
@@ -164,6 +171,7 @@ class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListene
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null
headBinding = null
} }
override fun onItemClick(view: View?, adapterPosition: Int) { override fun onItemClick(view: View?, adapterPosition: Int) {

View File

@@ -12,6 +12,7 @@ import com.navinfo.volvo.model.network.NetworkDeleteMessagePost
import com.navinfo.volvo.model.network.NetworkMessageListPost import com.navinfo.volvo.model.network.NetworkMessageListPost
import com.navinfo.volvo.repository.database.DatabaseRepository import com.navinfo.volvo.repository.database.DatabaseRepository
import com.navinfo.volvo.repository.network.NetworkRepository import com.navinfo.volvo.repository.network.NetworkRepository
import com.navinfo.volvo.repository.preferences.PreferencesRepository
import com.navinfo.volvo.util.NetResult import com.navinfo.volvo.util.NetResult
import com.navinfo.volvo.util.asLiveData import com.navinfo.volvo.util.asLiveData
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@@ -25,25 +26,35 @@ class HomeViewModel @Inject constructor(
private val netRepository: NetworkRepository, private val netRepository: NetworkRepository,
private val dataRepository: DatabaseRepository, private val dataRepository: DatabaseRepository,
private val messageDao: GreetingMessageDao, private val messageDao: GreetingMessageDao,
private val shard: PreferencesRepository
) : ViewModel() { ) : ViewModel() {
private val _isLoading = MutableLiveData<Boolean>() private val _isLoading = MutableLiveData<Boolean>()
val isLoading = _isLoading.asLiveData() val isLoading = _isLoading.asLiveData()
// private val _messageList = MutableLiveData<List<GreetingMessage>>() // private val _messageList = MutableLiveData<List<GreetingMessage>>()
// val messageList = _messageList.asLiveData() // val messageList = _messageList.asLiveData()
val messageList: Flow<PagingData<GreetingMessage>> val messageList: Flow<PagingData<GreetingMessage>>
get() = dataRepository.getMessageByPaging() get() = dataRepository.getMessageByPaging()
lateinit var userName: String
init {
viewModelScope.launch {
shard.loginUser().collect {
userName = it!!.username
}
}
}
fun getNetMessageList() { fun getNetMessageList() {
if (_isLoading.value == true) if (_isLoading.value == true)
return return
_isLoading.postValue(true) _isLoading.postValue(true)
viewModelScope.launch { viewModelScope.launch {
val messagePost = NetworkMessageListPost(who = "", toWho = "") val messagePost = NetworkMessageListPost(who = userName, toWho = "")
when (val result = netRepository.getMessageList(messagePost)) { when (val result = netRepository.getMessageList(messagePost)) {
is NetResult.Success -> { is NetResult.Success -> {
_isLoading.value = false _isLoading.value = false
@@ -70,13 +81,18 @@ class HomeViewModel @Inject constructor(
viewModelScope.launch { viewModelScope.launch {
val post = NetworkDeleteMessagePost(id) val post = NetworkDeleteMessagePost(id)
netRepository.deleteMessage(post) netRepository.deleteMessage(post)
messageDao.deleteById(id)
when (val result = netRepository.deleteMessage(post)) { when (val result = netRepository.deleteMessage(post)) {
is NetResult.Success -> { is NetResult.Success -> {
_isLoading.value = false _isLoading.value = false
} }
is NetResult.Failure -> { is NetResult.Failure -> {
_isLoading.value = false _isLoading.value = false
Toast.makeText(application, "${result.code}:${result.msg}", Toast.LENGTH_SHORT) Toast.makeText(
application,
"服务返回信息:${result.code}:${result.msg}",
Toast.LENGTH_SHORT
)
.show() .show()
} }
is NetResult.Error -> { is NetResult.Error -> {

View File

@@ -45,7 +45,6 @@ class LoginFragment : BaseFragment() {
if (it != null){ if (it != null){
viewBinding.loginUser = it viewBinding.loginUser = it
} }
cancel()
} }
} }
viewBinding.loginFragmentRegisterButton.setOnClickListener { viewBinding.loginFragmentRegisterButton.setOnClickListener {

View File

@@ -15,14 +15,18 @@ import android.widget.ArrayAdapter
import android.widget.Toast import android.widget.Toast
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.easytools.tools.DateUtils import com.easytools.tools.DateUtils
import com.easytools.tools.DisplayUtils import com.easytools.tools.DisplayUtils
import com.easytools.tools.FileIOUtils import com.easytools.tools.FileIOUtils
import com.easytools.tools.ResourceUtils import com.easytools.tools.ResourceUtils
import com.easytools.tools.ThreadPoolUtils.runOnUiThread
import com.easytools.tools.ToastUtils import com.easytools.tools.ToastUtils
import com.elvishew.xlog.XLog import com.elvishew.xlog.XLog
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -42,8 +46,10 @@ import com.navinfo.volvo.util.PhotoLoader
import com.navinfo.volvo.utils.EasyMediaFile import com.navinfo.volvo.utils.EasyMediaFile
import com.navinfo.volvo.utils.SystemConstant import com.navinfo.volvo.utils.SystemConstant
import com.nhaarman.supertooltips.ToolTip import com.nhaarman.supertooltips.ToolTip
import dagger.hilt.android.AndroidEntryPoint
import indi.liyi.viewer.Utils import indi.liyi.viewer.Utils
import indi.liyi.viewer.ViewData import indi.liyi.viewer.ViewData
import kotlinx.coroutines.launch
import top.zibin.luban.Luban import top.zibin.luban.Luban
import top.zibin.luban.OnCompressListener import top.zibin.luban.OnCompressListener
import java.io.File import java.io.File
@@ -51,12 +57,10 @@ import java.io.FileInputStream
import java.util.* import java.util.*
//@RuntimePermissions @AndroidEntryPoint
class ObtainMessageFragment: Fragment() { class ObtainMessageFragment : Fragment() {
private var _binding: FragmentObtainMessageBinding? = null private var _binding: FragmentObtainMessageBinding? = null
private val obtainMessageViewModel by lazy { private val obtainMessageViewModel by viewModels<ObtainMessageViewModel>()
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java)
}
private val photoHelper by lazy { private val photoHelper by lazy {
EasyMediaFile().setCrop(true) EasyMediaFile().setCrop(true)
} }
@@ -79,17 +83,17 @@ class ObtainMessageFragment: Fragment() {
_binding = FragmentObtainMessageBinding.inflate(inflater, container, false) _binding = FragmentObtainMessageBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root
obtainMessageViewModel.setCurrentMessage(GreetingMessage()) obtainMessageViewModel.setCurrentMessage(GreetingMessage(who = obtainMessageViewModel.username))
obtainMessageViewModel?.getMessageLiveData()?.observe( obtainMessageViewModel.getMessageLiveData().observe(
viewLifecycleOwner, Observer { viewLifecycleOwner, Observer {
// 初始化界面显示内容 // 初始化界面显示内容
if(it.name?.isNotEmpty() == true) if (it.name?.isNotEmpty() == true)
binding.tvMessageTitle?.setText(it.name) binding.tvMessageTitle?.setText(it.name)
if (it.sendDate?.isNotEmpty() == true) { if (it.sendDate?.isNotEmpty() == true) {
// 获取当前发送时间,如果早于当前时间,则显示现在 // 获取当前发送时间,如果早于当前时间,则显示现在
val sendDate = DateUtils.str2Date(it.sendDate, dateSendFormat) val sendDate = DateUtils.str2Date(it.sendDate, dateSendFormat)
if (sendDate<=Date()) { if (sendDate <= Date()) {
binding.btnSendTime.text = "现在" binding.btnSendTime.text = "现在"
} else { } else {
binding.btnSendTime.text = it.sendDate binding.btnSendTime.text = it.sendDate
@@ -99,39 +103,47 @@ class ObtainMessageFragment: Fragment() {
} }
var hasPhoto = false var hasPhoto = false
var hasAudio = false var hasAudio = false
if (it.imageUrl!=null&&it.imageUrl?.isNotEmpty() == true) { if (it.imageUrl != null && it.imageUrl?.isNotEmpty() == true) {
hasPhoto = true hasPhoto = true
// Glide.with(this@ObtainMessageFragment) // Glide.with(this@ObtainMessageFragment)
// .asBitmap().fitCenter() // .asBitmap().fitCenter()
// .load(it.imageUrl) // .load(it.imageUrl)
// .diskCacheStrategy(DiskCacheStrategy.ALL) // .diskCacheStrategy(DiskCacheStrategy.ALL)
// .into(binding.imgMessageAttachment) // .into(binding.imgMessageAttachment)
// 如果当前attachment文件是本地文件开始尝试网络上传 // 如果当前attachment文件是本地文件开始尝试网络上传
val str = it.imageUrl?.replace("\\", "/") val str = it.imageUrl?.replace("\\", "/")
binding.tvPhotoName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG ) binding.tvPhotoName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG)
if (!str!!.startsWith("http")) { if (!str!!.startsWith("http")) {
obtainMessageViewModel.uploadAttachment(File(it.imageUrl), AttachmentType.PIC) obtainMessageViewModel.uploadAttachment(
File(it.imageUrl),
AttachmentType.PIC
)
binding.tvPhotoName.text = str.substringAfterLast("/", "picture.jpg") binding.tvPhotoName.text = str.substringAfterLast("/", "picture.jpg")
} else { } else {
if (str.contains("?")) { if (str.contains("?")) {
binding.tvPhotoName.text = str.substring(str.lastIndexOf("/")+1, str.indexOf("?")) binding.tvPhotoName.text =
str.substring(str.lastIndexOf("/") + 1, str.indexOf("?"))
} else { } else {
binding.tvPhotoName.text = str.substringAfterLast("/") binding.tvPhotoName.text = str.substringAfterLast("/")
} }
} }
} }
if (it.mediaUrl!=null&&it.mediaUrl?.isNotEmpty() == true) { if (it.mediaUrl != null && it.mediaUrl?.isNotEmpty() == true) {
hasAudio = true hasAudio = true
binding.tvAudioName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG ) binding.tvAudioName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG)
// 如果当前attachment文件是本地文件开始尝试网络上传 // 如果当前attachment文件是本地文件开始尝试网络上传
val str = it.mediaUrl?.replace("\\", "/") val str = it.mediaUrl?.replace("\\", "/")
if (!str!!.startsWith("http")) { if (!str!!.startsWith("http")) {
obtainMessageViewModel.uploadAttachment(File(it.mediaUrl),AttachmentType.AUDIO) obtainMessageViewModel.uploadAttachment(
File(it.mediaUrl),
AttachmentType.AUDIO
)
binding.tvAudioName.text = str.substringAfterLast("/", "audio.m4a") binding.tvAudioName.text = str.substringAfterLast("/", "audio.m4a")
} else { } else {
if (str.contains("?")) { if (str.contains("?")) {
binding.tvAudioName.text = str.substring(str.lastIndexOf("/")+1, str.indexOf("?")) binding.tvAudioName.text =
str.substring(str.lastIndexOf("/") + 1, str.indexOf("?"))
} else { } else {
binding.tvAudioName.text = str.substringAfterLast("/") binding.tvAudioName.text = str.substringAfterLast("/")
} }
@@ -139,13 +151,16 @@ class ObtainMessageFragment: Fragment() {
} }
binding.layerPhotoResult.visibility = if (hasPhoto) VISIBLE else GONE binding.layerPhotoResult.visibility = if (hasPhoto) VISIBLE else GONE
binding.layerGetPhoto.visibility = if (hasPhoto) GONE else VISIBLE binding.layerGetPhoto.visibility = if (hasPhoto) GONE else VISIBLE
// binding.imgMessageAttachment.visibility = if (hasPhoto) VISIBLE else GONE // binding.imgMessageAttachment.visibility = if (hasPhoto) VISIBLE else GONE
binding.layerAudioResult.visibility = if (hasAudio) VISIBLE else GONE binding.layerAudioResult.visibility = if (hasAudio) VISIBLE else GONE
binding.layerGetAudio.visibility = if (hasAudio) GONE else VISIBLE binding.layerGetAudio.visibility = if (hasAudio) GONE else VISIBLE
// binding.llAudioPlay.visibility = if (hasAudio) VISIBLE else GONE // binding.llAudioPlay.visibility = if (hasAudio) VISIBLE else GONE
} }
) )
lifecycle.addObserver(recorderLifecycleObserver) lifecycle.addObserver(recorderLifecycleObserver)
initView() initView()
return root return root
@@ -158,7 +173,7 @@ class ObtainMessageFragment: Fragment() {
obtainMessageViewModel.getMessageLiveData().value?.name = it.toString() obtainMessageViewModel.getMessageLiveData().value?.name = it.toString()
}) })
binding.edtSendFrom.addTextChangedListener (afterTextChanged = { binding.edtSendFrom.addTextChangedListener(afterTextChanged = {
obtainMessageViewModel.getMessageLiveData().value?.who = it.toString() obtainMessageViewModel.getMessageLiveData().value?.who = it.toString()
}) })
@@ -171,9 +186,11 @@ class ObtainMessageFragment: Fragment() {
} }
val sendToArray = mutableListOf<String>("LYVXFEFEXNL754427") val sendToArray = mutableListOf<String>("LYVXFEFEXNL754427")
binding.edtSendTo.adapter = ArrayAdapter<String>(context!!, binding.edtSendTo.adapter = ArrayAdapter<String>(
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray) context!!,
binding.edtSendTo.onItemSelectedListener = object: OnItemSelectedListener { android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray
)
binding.edtSendTo.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) { override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2] obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2]
} }
@@ -190,9 +207,19 @@ class ObtainMessageFragment: Fragment() {
override fun onClickListener(selectTime: String) { override fun onClickListener(selectTime: String) {
val sendDate = DateUtils.str2Date(selectTime, dateShowFormat) val sendDate = DateUtils.str2Date(selectTime, dateShowFormat)
if (sendDate <= Date()) { if (sendDate <= Date()) {
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(Date(), dateSendFormat)) obtainMessageViewModel.updateMessageSendTime(
DateUtils.date2Str(
Date(),
dateSendFormat
)
)
} else { } else {
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(sendDate, dateSendFormat)) obtainMessageViewModel.updateMessageSendTime(
DateUtils.date2Str(
sendDate,
dateSendFormat
)
)
} }
} }
@@ -210,7 +237,8 @@ class ObtainMessageFragment: Fragment() {
override fun onGranted(permissions: MutableList<String>, all: Boolean) { override fun onGranted(permissions: MutableList<String>, all: Boolean) {
if (!all) { if (!all) {
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT).show() Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT)
.show()
return return
} }
// 开始启动拍照界面 // 开始启动拍照界面
@@ -259,18 +287,20 @@ class ObtainMessageFragment: Fragment() {
.request(object : OnPermissionCallback { .request(object : OnPermissionCallback {
override fun onGranted(permissions: MutableList<String>, all: Boolean) { override fun onGranted(permissions: MutableList<String>, all: Boolean) {
if (!all) { if (!all) {
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT).show() Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT)
.show()
return return
} }
when(motionEvent.action) { when (motionEvent.action) {
MotionEvent.ACTION_DOWN-> { MotionEvent.ACTION_DOWN -> {
// 申请权限 // 申请权限
recorderLifecycleObserver.initAndStartRecorder() recorderLifecycleObserver.initAndStartRecorder()
ToastUtils.showToast("开始录音!") ToastUtils.showToast("开始录音!")
false false
} }
MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> {
val recorderAudioPath = recorderLifecycleObserver.stopAndReleaseRecorder() val recorderAudioPath =
recorderLifecycleObserver.stopAndReleaseRecorder()
if (File(recorderAudioPath).exists()) { if (File(recorderAudioPath).exists()) {
obtainMessageViewModel.updateMessageAudio(recorderAudioPath) obtainMessageViewModel.updateMessageAudio(recorderAudioPath)
} }
@@ -300,7 +330,7 @@ class ObtainMessageFragment: Fragment() {
photoHelper.setCallback { photoHelper.setCallback {
if (it.exists()) { if (it.exists()) {
val fileName = it.name.lowercase() val fileName = it.name.lowercase()
if (fileName.endsWith(".jpg")||fileName.endsWith(".jpeg")||fileName.endsWith(".png")) { if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") || fileName.endsWith(".png")) {
// 获取选中的图片,自动压缩图片质量 // 获取选中的图片,自动压缩图片质量
// 压缩图片文件 // 压缩图片文件
Luban.with(context) Luban.with(context)
@@ -324,13 +354,25 @@ class ObtainMessageFragment: Fragment() {
} }
// 如果当前文件不在camera缓存文件夹下则移动该文件 // 如果当前文件不在camera缓存文件夹下则移动该文件
if (!file!!.parentFile.absolutePath.equals(SystemConstant.CameraFolder)) { if (!file!!.parentFile.absolutePath.equals(SystemConstant.CameraFolder)) {
val copyResult = FileIOUtils.writeFileFromIS(File(SystemConstant.CameraFolder, fileName), FileInputStream(file)) val copyResult = FileIOUtils.writeFileFromIS(
XLog.e("拷贝结果:"+copyResult) File(
SystemConstant.CameraFolder,
fileName
), FileInputStream(file)
)
XLog.e("拷贝结果:" + copyResult)
// 跳转回原Fragment展示拍摄的照片 // 跳转回原Fragment展示拍摄的照片
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java).updateMessagePic(File(SystemConstant.CameraFolder, fileName).absolutePath) ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java)
.updateMessagePic(
File(
SystemConstant.CameraFolder,
fileName
).absolutePath
)
} else { } else {
// 跳转回原Fragment展示拍摄的照片 // 跳转回原Fragment展示拍摄的照片
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java).updateMessagePic(file!!.absolutePath) ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java)
.updateMessagePic(file!!.absolutePath)
} }
} }
@@ -338,12 +380,23 @@ class ObtainMessageFragment: Fragment() {
XLog.d("压缩图片失败:${e.message}") XLog.d("压缩图片失败:${e.message}")
} }
}).launch() }).launch()
} else if (fileName.endsWith(".mp3")||fileName.endsWith(".wav")||fileName.endsWith(".amr")||fileName.endsWith(".m4a")) { } else if (fileName.endsWith(".mp3") || fileName.endsWith(".wav") || fileName.endsWith(
".amr"
) || fileName.endsWith(".m4a")
) {
ToastUtils.showToast(it.absolutePath) ToastUtils.showToast(it.absolutePath)
if (!it.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) { if (!it.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
val copyResult = FileIOUtils.writeFileFromIS(File(SystemConstant.SoundFolder, fileName), FileInputStream(it)) val copyResult = FileIOUtils.writeFileFromIS(
XLog.e("拷贝结果:"+copyResult) File(SystemConstant.SoundFolder, fileName),
obtainMessageViewModel.updateMessageAudio(File(SystemConstant.SoundFolder, fileName).absolutePath) FileInputStream(it)
)
XLog.e("拷贝结果:" + copyResult)
obtainMessageViewModel.updateMessageAudio(
File(
SystemConstant.SoundFolder,
fileName
).absolutePath
)
} else { } else {
obtainMessageViewModel.updateMessageAudio(it.absolutePath) obtainMessageViewModel.updateMessageAudio(it.absolutePath)
} }
@@ -356,12 +409,14 @@ class ObtainMessageFragment: Fragment() {
} }
binding.tvAudioName.setOnClickListener { binding.tvAudioName.setOnClickListener {
binding.llAudioPlay.visibility = if (binding.llAudioPlay.visibility == VISIBLE) GONE else VISIBLE binding.llAudioPlay.visibility =
if (binding.llAudioPlay.visibility == VISIBLE) GONE else VISIBLE
// 判断当前播放的文件是否在缓存文件夹内,如果不在首先下载该文件 // 判断当前播放的文件是否在缓存文件夹内,如果不在首先下载该文件
val fileUrl = obtainMessageViewModel.getMessageLiveData().value!!.mediaUrl!! val fileUrl = obtainMessageViewModel.getMessageLiveData().value!!.mediaUrl!!
val localFile = obtainMessageViewModel.getLocalFileFromNetUrl(fileUrl, AttachmentType.AUDIO) val localFile =
obtainMessageViewModel.getLocalFileFromNetUrl(fileUrl, AttachmentType.AUDIO)
if (!localFile.exists()) { if (!localFile.exists()) {
obtainMessageViewModel.downLoadFile(fileUrl, localFile, object: DownloadCallback { obtainMessageViewModel.downLoadFile(fileUrl, localFile, object : DownloadCallback {
override fun progress(progress: Int) { override fun progress(progress: Int) {
} }
@@ -379,7 +434,7 @@ class ObtainMessageFragment: Fragment() {
} }
binding.btnObtainMessageBack.setOnClickListener { binding.btnObtainMessageBack.setOnClickListener {
Navigation.findNavController(it).popBackStack() findNavController().popBackStack()
} }
binding.btnObtainMessageConfirm.setOnClickListener { binding.btnObtainMessageConfirm.setOnClickListener {
@@ -400,7 +455,7 @@ class ObtainMessageFragment: Fragment() {
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tiLayoutTitle) toolTipRelativeLayout.showToolTipForView(toolTip, binding.tiLayoutTitle)
checkResult = false checkResult = false
} else { } else {
if (messageData?.name!!.length>10) { if (messageData?.name!!.length > 10) {
val toolTipRelativeLayout = val toolTipRelativeLayout =
binding.ttTitle binding.ttTitle
val toolTip = ToolTip() val toolTip = ToolTip()
@@ -438,7 +493,7 @@ class ObtainMessageFragment: Fragment() {
checkResult = false checkResult = false
} }
if (messageData?.who?.isEmpty()==true) { if (messageData?.who?.isEmpty() == true) {
val toolTipRelativeLayout = val toolTipRelativeLayout =
binding.ttSendFrom binding.ttSendFrom
val toolTip = ToolTip() val toolTip = ToolTip()
@@ -450,7 +505,7 @@ class ObtainMessageFragment: Fragment() {
toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendFrom) toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendFrom)
checkResult = false checkResult = false
} }
if (messageData?.toWho?.isEmpty()==true) { if (messageData?.toWho?.isEmpty() == true) {
val toolTipRelativeLayout = val toolTipRelativeLayout =
binding.ttSendTo binding.ttSendTo
val toolTip = ToolTip() val toolTip = ToolTip()
@@ -471,21 +526,29 @@ class ObtainMessageFragment: Fragment() {
localAttachmentList.add(imageAttachment) localAttachmentList.add(imageAttachment)
} }
if (messageData?.mediaUrl?.startsWith("http") == false) { if (messageData?.mediaUrl?.startsWith("http") == false) {
val audioAttachment = Attachment("", messageData.mediaUrl!!, AttachmentType.AUDIO) val audioAttachment =
Attachment("", messageData.mediaUrl!!, AttachmentType.AUDIO)
localAttachmentList.add(audioAttachment) localAttachmentList.add(audioAttachment)
} }
if (localAttachmentList.isNotEmpty()) { if (localAttachmentList.isNotEmpty()) {
MaterialAlertDialogBuilder(context!!) MaterialAlertDialogBuilder(context!!)
.setTitle("提示") .setTitle("提示")
.setMessage("当前照片及音频内容需首先上传,是否尝试上传?") .setMessage("当前照片及音频内容需首先上传,是否尝试上传?")
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i -> .setPositiveButton(
"确定",
DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss() dialogInterface.dismiss()
for (attachment in localAttachmentList) { for (attachment in localAttachmentList) {
obtainMessageViewModel.uploadAttachment(File(attachment.pathUrl), attachment.attachmentType) obtainMessageViewModel.uploadAttachment(
File(attachment.pathUrl),
attachment.attachmentType
)
} }
}) })
.setNegativeButton("取消", DialogInterface.OnClickListener { .setNegativeButton(
dialogInterface, i -> dialogInterface.dismiss() "取消",
DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss()
}) })
.show() .show()
return@setOnClickListener return@setOnClickListener
@@ -495,14 +558,14 @@ class ObtainMessageFragment: Fragment() {
val sendDate = DateUtils.str2Date(messageData?.sendDate, dateSendFormat) val sendDate = DateUtils.str2Date(messageData?.sendDate, dateSendFormat)
val cal = Calendar.getInstance() val cal = Calendar.getInstance()
cal.time = Date() cal.time = Date()
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE)+1) cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE) + 1)
if (cal.time.time < sendDate.time) { // 发送时间设置小于当前时间1分钟前Toast提示用户并自动设置发送时间 if (cal.time.time < sendDate.time) { // 发送时间设置小于当前时间1分钟前Toast提示用户并自动设置发送时间
messageData?.sendDate = DateUtils.date2Str(cal.time, dateSendFormat) messageData?.sendDate = DateUtils.date2Str(cal.time, dateSendFormat)
ToastUtils.showToast("自动调整发送时间为1分钟后发送") ToastUtils.showToast("自动调整发送时间为1分钟后发送")
} }
// 开始网络提交数据 // 开始网络提交数据
if (obtainMessageViewModel.getMessageLiveData().value?.id==0L) { // 如果网络id为空则调用更新操作 if (obtainMessageViewModel.getMessageLiveData().value?.id == 0L) { // 如果网络id为空则调用更新操作
obtainMessageViewModel.insertCardByApp(confirmCallback) obtainMessageViewModel.insertCardByApp(confirmCallback)
} else { } else {
obtainMessageViewModel.updateCardByApp(confirmCallback) obtainMessageViewModel.updateCardByApp(confirmCallback)
@@ -514,7 +577,8 @@ class ObtainMessageFragment: Fragment() {
val viewData = ViewData() val viewData = ViewData()
viewData.imageSrc = obtainMessageViewModel.getMessageLiveData().value!!.imageUrl viewData.imageSrc = obtainMessageViewModel.getMessageLiveData().value!!.imageUrl
viewData.targetX = Utils.dp2px(context, 10F).toFloat() viewData.targetX = Utils.dp2px(context, 10F).toFloat()
viewData.targetWidth = DisplayUtils.getScreenWidthPixels(activity) - Utils.dp2px(context, 20F) viewData.targetWidth =
DisplayUtils.getScreenWidthPixels(activity) - Utils.dp2px(context, 20F)
viewData.targetHeight = Utils.dp2px(context, 200F) viewData.targetHeight = Utils.dp2px(context, 200F)
val viewDataList = listOf(viewData) val viewDataList = listOf(viewData)
binding.imageViewer.overlayStatusBar(true) // ImageViewer 是否会占据 StatusBar 的空间 binding.imageViewer.overlayStatusBar(true) // ImageViewer 是否会占据 StatusBar 的空间
@@ -524,11 +588,13 @@ class ObtainMessageFragment: Fragment() {
.watch(0) // 开启浏览 .watch(0) // 开启浏览
} }
binding.edtSendFrom.setText(obtainMessageViewModel.username)
} }
val confirmCallback = object: ObtainMessageViewModel.MyConfirmCallback { val confirmCallback = object : ObtainMessageViewModel.MyConfirmCallback {
override fun onSucess() { override fun onSucess() {
findNavController().navigate(R.id.navigation_home) findNavController().popBackStack()
} }
} }
@@ -569,6 +635,7 @@ class ObtainMessageFragment: Fragment() {
}) })
.show() .show()
} }
fun onRecorderDenied() { fun onRecorderDenied() {
ToastUtils.showToast("当前操作需要您授权录音权限!") ToastUtils.showToast("当前操作需要您授权录音权限!")
} }

View File

@@ -1,36 +1,48 @@
package com.navinfo.volvo.ui.fragments.message package com.navinfo.volvo.ui.fragments.message
import android.security.ConfirmationCallback import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.* import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.easytools.tools.FileIOUtils import com.easytools.tools.FileIOUtils
import com.easytools.tools.FileUtils import com.easytools.tools.FileUtils
import com.easytools.tools.ToastUtils import com.easytools.tools.ToastUtils
import com.elvishew.xlog.XLog import com.elvishew.xlog.XLog
import com.navinfo.volvo.database.entity.Attachment
import com.navinfo.volvo.database.entity.AttachmentType import com.navinfo.volvo.database.entity.AttachmentType
import com.navinfo.volvo.database.entity.GreetingMessage import com.navinfo.volvo.database.entity.GreetingMessage
import com.navinfo.volvo.http.DownloadCallback import com.navinfo.volvo.http.DownloadCallback
import com.navinfo.volvo.http.DownloadManager import com.navinfo.volvo.http.DownloadManager
import com.navinfo.volvo.http.DownloadState import com.navinfo.volvo.http.DownloadState
import com.navinfo.volvo.http.NavinfoVolvoCall import com.navinfo.volvo.http.NavinfoVolvoCall
import com.navinfo.volvo.model.proto.LoginUser
import com.navinfo.volvo.repository.preferences.PreferencesRepository
import com.navinfo.volvo.utils.SystemConstant import com.navinfo.volvo.utils.SystemConstant
import kotlinx.coroutines.flow.Flow import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody import okhttp3.RequestBody
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.util.*
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel
class ObtainMessageViewModel @Inject constructor(): ViewModel() { class ObtainMessageViewModel @Inject constructor(
private val pre: PreferencesRepository
) : ViewModel() {
private val msgLiveData: MutableLiveData<GreetingMessage> by lazy { private val msgLiveData: MutableLiveData<GreetingMessage> by lazy {
MutableLiveData<GreetingMessage>() MutableLiveData<GreetingMessage>()
} }
lateinit var username: String
init {
viewModelScope.launch {
pre.loginUser().collect {
username = it!!.username
}
}
}
fun setCurrentMessage(msg: GreetingMessage) { fun setCurrentMessage(msg: GreetingMessage) {
msgLiveData.postValue(msg) msgLiveData.postValue(msg)
} }
@@ -131,7 +143,11 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
try { try {
val requestFile: RequestBody = val requestFile: RequestBody =
RequestBody.create("multipart/form-data".toMediaTypeOrNull(), attachmentFile) RequestBody.create("multipart/form-data".toMediaTypeOrNull(), attachmentFile)
val body = MultipartBody.Part.createFormData("picture", attachmentFile.getName(), requestFile) val body = MultipartBody.Part.createFormData(
"picture",
attachmentFile.getName(),
requestFile
)
val result = NavinfoVolvoCall.getApi().uploadAttachment(body) val result = NavinfoVolvoCall.getApi().uploadAttachment(body)
XLog.d(result.code) XLog.d(result.code)
if (result.code == 200) { // 请求成功 if (result.code == 200) { // 请求成功
@@ -144,17 +160,19 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
if (destFile.exists()) { if (destFile.exists()) {
FileUtils.deleteFile(destFile) FileUtils.deleteFile(destFile)
} }
val copyResult = FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile)) val copyResult =
XLog.e("拷贝结果:"+copyResult) FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile))
XLog.e("拷贝结果:" + copyResult)
} else { } else {
val destFile = File(SystemConstant.SoundFolder, newFileName) val destFile = File(SystemConstant.SoundFolder, newFileName)
if (destFile.exists()) { if (destFile.exists()) {
FileUtils.deleteFile(destFile) FileUtils.deleteFile(destFile)
} }
val copyResult = FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile)) val copyResult =
XLog.e("拷贝结果:"+copyResult) FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile))
XLog.e("拷贝结果:" + copyResult)
} }
if (fileKey!=null) { if (fileKey != null) {
downloadAttachment(fileKey, attachmentType) downloadAttachment(fileKey, attachmentType)
} }
} else { } else {
@@ -178,7 +196,7 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
if (result.code == 200) { // 请求成功 if (result.code == 200) { // 请求成功
// 获取上传后的结果 // 获取上传后的结果
val imageUrl = result.data val imageUrl = result.data
if (imageUrl!=null) { if (imageUrl != null) {
XLog.d("downloadAttachment-imageUrl:${imageUrl}") XLog.d("downloadAttachment-imageUrl:${imageUrl}")
// 获取到图片的网络地址 // 获取到图片的网络地址
if (attachmentType == AttachmentType.PIC) { if (attachmentType == AttachmentType.PIC) {
@@ -197,7 +215,7 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
} }
} }
fun downLoadFile(url: String, destFile: File, downloadCallback: DownloadCallback){ fun downLoadFile(url: String, destFile: File, downloadCallback: DownloadCallback) {
viewModelScope.launch { viewModelScope.launch {
DownloadManager.download( DownloadManager.download(
url, url,
@@ -234,7 +252,8 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
"toWho" to message?.toWho, "toWho" to message?.toWho,
"sendDate" to message?.sendDate "sendDate" to message?.sendDate
) )
val result = NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>) val result =
NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>)
XLog.d("insertCardByApp:${result.code}") XLog.d("insertCardByApp:${result.code}")
if (result.code == 200) { // 请求成功 if (result.code == 200) { // 请求成功
// 获取上传后的结果 // 获取上传后的结果
@@ -266,7 +285,8 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
"toWho" to message?.toWho, "toWho" to message?.toWho,
"sendDate" to message?.sendDate "sendDate" to message?.sendDate
) )
val result = NavinfoVolvoCall.getApi().updateCardByApp(updateData as Map<String, String>) val result =
NavinfoVolvoCall.getApi().updateCardByApp(updateData as Map<String, String>)
XLog.d("updateCardByApp:${result.code}") XLog.d("updateCardByApp:${result.code}")
if (result.code == 200) { // 请求成功 if (result.code == 200) { // 请求成功
// 数据更新成功 // 数据更新成功
@@ -286,14 +306,14 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
/** /**
* 根据网络地址获取本地的缓存文件路径 * 根据网络地址获取本地的缓存文件路径
* */ * */
fun getLocalFileFromNetUrl(url: String, attachmentType: AttachmentType):File { fun getLocalFileFromNetUrl(url: String, attachmentType: AttachmentType): File {
if (url.startsWith("http")) { if (url.startsWith("http")) {
val folder = when(attachmentType) { val folder = when (attachmentType) {
AttachmentType.PIC-> SystemConstant.CameraFolder AttachmentType.PIC -> SystemConstant.CameraFolder
else -> SystemConstant.SoundFolder else -> SystemConstant.SoundFolder
} }
var name = if (url.contains("?")) { var name = if (url.contains("?")) {
url.substring(url.lastIndexOf("/")+1, url.indexOf("?")) url.substring(url.lastIndexOf("/") + 1, url.indexOf("?"))
} else { } else {
url.substringAfterLast("/") url.substringAfterLast("/")
} }

View File

@@ -17,12 +17,14 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ImageView <androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/message_head_icon" android:id="@+id/message_head_icon"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:src="@mipmap/volvo_logo_small" android:scaleType="fitXY"
android:src="@mipmap/ic_launcher"
app:roundPercent="0.4"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View File

@@ -14,10 +14,11 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context="com.navinfo.volvo.ui.fragments.login.LoginFragment"> tools:context="com.navinfo.volvo.ui.fragments.login.LoginFragment">
<androidx.constraintlayout.utils.widget.ImageFilterView <ImageView
android:id="@+id/login_fragment_logo" android:id="@+id/login_fragment_logo"
android:layout_width="wrap_content" android:layout_width="100dp"
android:layout_height="wrap_content" android:layout_height="100dp"
android:scaleType="fitXY"
android:src="@mipmap/volvo_logo_small" android:src="@mipmap/volvo_logo_small"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -6,7 +6,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/activity_default_padding" android:padding="@dimen/activity_default_padding"
tools:context=".ui.message.ObtainMessageFragment"> tools:context="com.navinfo.volvo.ui.fragments.message.ObtainMessageFragment">
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@@ -300,6 +300,7 @@
android:text="我是谁:"></TextView> android:text="我是谁:"></TextView>
<androidx.appcompat.widget.AppCompatEditText <androidx.appcompat.widget.AppCompatEditText
android:enabled="false"
android:id="@+id/edt_send_from" android:id="@+id/edt_send_from"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -333,6 +334,13 @@
android:id="@+id/edt_send_to" android:id="@+id/edt_send_to"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"></androidx.appcompat.widget.AppCompatSpinner> android:layout_height="wrap_content"></androidx.appcompat.widget.AppCompatSpinner>
<indi.liyi.viewer.ImageViewer
android:id="@+id/imageViewer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
app:ivr_dragMode="agile" />
</LinearLayout> </LinearLayout>
<com.nhaarman.supertooltips.ToolTipRelativeLayout <com.nhaarman.supertooltips.ToolTipRelativeLayout
@@ -404,10 +412,4 @@
android:text="确认提交"></com.google.android.material.button.MaterialButton> android:text="确认提交"></com.google.android.material.button.MaterialButton>
</LinearLayout> </LinearLayout>
<indi.liyi.viewer.ImageViewer
android:id="@+id/imageViewer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
app:ivr_dragMode="agile" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="暂无数据,可下拉刷新"
android:textSize="16sp" />
</androidx.constraintlayout.widget.ConstraintLayout>