消息列表
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package com.example.defenseapplication.bean
|
||||
|
||||
data class MessageItem(
|
||||
data class MessageBean(
|
||||
val id: String,
|
||||
val userId: String,
|
||||
val deviceId: String,
|
||||
@@ -10,9 +10,4 @@ data class MessageItem(
|
||||
val imageUrl: String?,
|
||||
val video: String?,
|
||||
val createTime: String
|
||||
)
|
||||
|
||||
data class MessageGroup(
|
||||
val time: String,
|
||||
val list: List<MessageItem>
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.example.defenseapplication.bean
|
||||
|
||||
data class MessageListResponse(
|
||||
val total: Int,
|
||||
val rows: List<MessageBean>
|
||||
)
|
||||
@@ -267,17 +267,7 @@ class HomeMenuFragment : Fragment() {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getMessage()
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200 && response.data != null) {
|
||||
val messageGroups = response.data as List<*>
|
||||
var unreadCount = 0
|
||||
messageGroups.forEach { group ->
|
||||
if (group is Map<*, *>) {
|
||||
val list = group["list"] as? List<*>
|
||||
list?.let { unreadCount += it.size }
|
||||
}
|
||||
}
|
||||
MessageStatusManager.setUnreadCount(unreadCount)
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
||||
@@ -2,15 +2,11 @@ package com.example.defenseapplication.home
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.adapter.MessageListAdapter
|
||||
import com.example.defenseapplication.adapter.MessageListItem
|
||||
import com.example.defenseapplication.bean.MessageGroup
|
||||
import com.example.defenseapplication.bean.MessageItem
|
||||
import com.example.defenseapplication.databinding.MessageActivityBinding
|
||||
import com.example.defenseapplication.utils.MessageStatusManager
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
@@ -23,6 +19,13 @@ import kotlinx.coroutines.withContext
|
||||
class MessageActivity : AppCompatActivity() {
|
||||
private lateinit var binding: MessageActivityBinding
|
||||
private val messageAdapter by lazy { MessageListAdapter() }
|
||||
|
||||
private var currentPage = 1
|
||||
private val pageSize = 10
|
||||
private var isLoading = false
|
||||
private var hasMoreData = true
|
||||
private val allMessages = mutableListOf<com.example.defenseapplication.bean.MessageBean>()
|
||||
private var lastLoadedCount = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -41,53 +44,132 @@ class MessageActivity : AppCompatActivity() {
|
||||
binding.ivBack.setOnClickListener { finish() }
|
||||
binding.rvMessageList.layoutManager = LinearLayoutManager(this)
|
||||
binding.rvMessageList.adapter = messageAdapter
|
||||
|
||||
binding.rvMessageList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||
val totalItemCount = layoutManager.itemCount
|
||||
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
|
||||
|
||||
if (!isLoading && hasMoreData && lastVisibleItem >= totalItemCount - 3 && dy > 0) {
|
||||
loadMoreData()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE && !hasMoreData && !isLoading) {
|
||||
showNoMoreDataHint()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun loadMessageList() {
|
||||
if (isLoading) return
|
||||
|
||||
isLoading = true
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getMessage()
|
||||
if (response.code == 0 && response.data != null) {
|
||||
val messageGroups = response.data as List<MessageGroup>
|
||||
val items = convertToMessageListItems(messageGroups)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (items.isEmpty()) {
|
||||
val messageResponse = RetrofitNetwork.getNetworkService().getMessage(
|
||||
pageNum = currentPage,
|
||||
pageSize = pageSize
|
||||
)
|
||||
println("total: ${messageResponse.total}")
|
||||
println("rows size: ${messageResponse.rows.size}")
|
||||
println("当前页:$currentPage, 加载条数:${messageResponse.rows.size}")
|
||||
|
||||
val newMessages = messageResponse.rows
|
||||
val loadedCount = newMessages.size
|
||||
|
||||
if (loadedCount < pageSize) {
|
||||
hasMoreData = false
|
||||
}
|
||||
|
||||
if (newMessages.isEmpty()) {
|
||||
if (currentPage == 1) {
|
||||
withContext(Dispatchers.Main) {
|
||||
showEmptyState()
|
||||
} else {
|
||||
hideEmptyState()
|
||||
messageAdapter.submitList(items)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (currentPage == 1) {
|
||||
allMessages.clear()
|
||||
}
|
||||
allMessages.addAll(newMessages)
|
||||
lastLoadedCount = loadedCount
|
||||
|
||||
val items = convertToMessageListItems(allMessages)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
hideEmptyState()
|
||||
messageAdapter.submitList(items)
|
||||
|
||||
if (!hasMoreData) {
|
||||
showNoMoreDataHint()
|
||||
} else {
|
||||
hideNoMoreDataHint()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
if (allMessages.isEmpty()) {
|
||||
println("items is empty, showing empty state")
|
||||
showEmptyState()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("Exception: ${e.message}")
|
||||
e.printStackTrace()
|
||||
withContext(Dispatchers.Main) {
|
||||
showEmptyState()
|
||||
if (allMessages.isEmpty()) {
|
||||
showEmptyState()
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadMoreData() {
|
||||
if (!hasMoreData || isLoading) return
|
||||
|
||||
currentPage++
|
||||
loadMessageList()
|
||||
}
|
||||
|
||||
private fun showEmptyState() {
|
||||
binding.contentLayout.visibility = View.GONE
|
||||
binding.rvMessageList.visibility = View.GONE
|
||||
binding.emptyLayout.visibility = View.VISIBLE
|
||||
binding.tvNoMoreData.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun hideEmptyState() {
|
||||
binding.contentLayout.visibility = View.VISIBLE
|
||||
binding.rvMessageList.visibility = View.VISIBLE
|
||||
binding.emptyLayout.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun showNoMoreDataHint() {
|
||||
binding.tvNoMoreData.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun hideNoMoreDataHint() {
|
||||
binding.tvNoMoreData.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun convertToMessageListItems(groups: List<MessageGroup>): List<MessageListItem> {
|
||||
private fun convertToMessageListItems(messages: List<com.example.defenseapplication.bean.MessageBean>): List<MessageListItem> {
|
||||
val items = mutableListOf<MessageListItem>()
|
||||
groups.forEach { group ->
|
||||
val headerTitle = formatDate(group.time)
|
||||
val groupedMessages = messages.groupBy { extractDate(it.createTime) }
|
||||
groupedMessages.forEach { (date, messageList) ->
|
||||
val headerTitle = formatDate(date)
|
||||
messageList.forEachIndexed { index, message ->
|
||||
println(" 消息${index + 1}: id=${message.id}, categoryName=${message.categoryName}, createTime=${message.createTime}")
|
||||
}
|
||||
items.add(MessageListItem.Header(headerTitle))
|
||||
group.list.forEach { message ->
|
||||
messageList.forEach { message ->
|
||||
items.add(
|
||||
MessageListItem.Message(
|
||||
time = extractTime(message.createTime),
|
||||
@@ -101,9 +183,24 @@ class MessageActivity : AppCompatActivity() {
|
||||
return items
|
||||
}
|
||||
|
||||
private fun extractDate(dateTime: String): String {
|
||||
return if (dateTime.contains(" ")) {
|
||||
dateTime.split(" ")[0]
|
||||
} else {
|
||||
dateTime
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDate(dateStr: String): String {
|
||||
return if (dateStr == "今天" || dateStr.contains("今天")) {
|
||||
"今天"
|
||||
} else if (dateStr.contains("-")) {
|
||||
val parts = dateStr.split("-")
|
||||
if (parts.size >= 3) {
|
||||
"${parts[1]}-${parts[2]}"
|
||||
} else {
|
||||
dateStr
|
||||
}
|
||||
} else {
|
||||
dateStr
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.pm.PackageManager
|
||||
import android.media.MediaRecorder
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.animation.ScaleAnimation
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
@@ -23,6 +22,10 @@ import android.content.res.Configuration
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import chuangyuan.ycj.videolibrary.listener.VideoInfoListener
|
||||
import chuangyuan.ycj.videolibrary.video.VideoPlayerManager
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
|
||||
private const val TAG = "LiveVideoActivity"
|
||||
//智能防御机A1
|
||||
@@ -35,6 +38,8 @@ class LiveVideoActivity : BaseActivity() {
|
||||
private var isRecording = false
|
||||
private var mediaRecorder: MediaRecorder? = null
|
||||
private var micPulseAnimation: ScaleAnimation? = null
|
||||
private var isFullscreen = false
|
||||
private var fullscreenBackButton: ImageView? = null
|
||||
|
||||
private val requestPermissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
@@ -112,6 +117,78 @@ class LiveVideoActivity : BaseActivity() {
|
||||
.create()
|
||||
|
||||
exoPlayerManager.startPlayer()
|
||||
|
||||
setupFullscreenListener()
|
||||
}
|
||||
|
||||
private fun setupFullscreenListener() {
|
||||
binding.exoPlayContextId.setOnClickListener {
|
||||
if (!isFullscreen) {
|
||||
enterFullscreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun enterFullscreen() {
|
||||
isFullscreen = true
|
||||
|
||||
binding.topBar.visibility = View.GONE
|
||||
binding.functionBar.visibility = View.GONE
|
||||
|
||||
val params = binding.exoPlayContextId.layoutParams
|
||||
params.width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
params.height = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
binding.exoPlayContextId.layoutParams = params
|
||||
|
||||
exoPlayerManager.onConfigurationChanged(Configuration().apply {
|
||||
orientation = Configuration.ORIENTATION_LANDSCAPE
|
||||
})
|
||||
|
||||
showFullscreenBackButton()
|
||||
}
|
||||
|
||||
private fun exitFullscreen() {
|
||||
isFullscreen = false
|
||||
|
||||
binding.topBar.visibility = View.VISIBLE
|
||||
binding.functionBar.visibility = View.VISIBLE
|
||||
|
||||
val params = binding.exoPlayContextId.layoutParams
|
||||
params.width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
params.height = 250
|
||||
binding.exoPlayContextId.layoutParams = params
|
||||
|
||||
exoPlayerManager.onConfigurationChanged(Configuration().apply {
|
||||
orientation = Configuration.ORIENTATION_PORTRAIT
|
||||
})
|
||||
|
||||
hideFullscreenBackButton()
|
||||
}
|
||||
|
||||
private fun showFullscreenBackButton() {
|
||||
fullscreenBackButton = ImageView(this).apply {
|
||||
setImageResource(R.drawable.back_white)
|
||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||
|
||||
val params = LinearLayout.LayoutParams(60, 60)
|
||||
params.topMargin = 60
|
||||
params.leftMargin = 20
|
||||
layoutParams = params
|
||||
|
||||
setOnClickListener {
|
||||
exitFullscreen()
|
||||
}
|
||||
}
|
||||
|
||||
(binding.root as ViewGroup).addView(fullscreenBackButton)
|
||||
fullscreenBackButton?.bringToFront()
|
||||
}
|
||||
|
||||
private fun hideFullscreenBackButton() {
|
||||
fullscreenBackButton?.let {
|
||||
(binding.root as ViewGroup).removeView(it)
|
||||
fullscreenBackButton = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
|
||||
@@ -13,7 +13,8 @@ import com.example.defenseapplication.bean.AddDeviceUserRequest
|
||||
import com.example.defenseapplication.bean.DeleteBean
|
||||
import com.example.defenseapplication.bean.DeleteDeviceUserRequest
|
||||
import com.example.defenseapplication.bean.FamilyMembersBean
|
||||
import com.example.defenseapplication.bean.MessageGroup
|
||||
import com.example.defenseapplication.bean.MessageBean
|
||||
import com.example.defenseapplication.bean.MessageListResponse
|
||||
import com.example.defenseapplication.bean.ObtainInviterInformationBean
|
||||
import com.example.defenseapplication.bean.ObtainInviterInformationRequest
|
||||
import com.example.defenseapplication.bean.SwitchFamilyRequest
|
||||
@@ -75,7 +76,10 @@ interface ApiService {
|
||||
* 查看消息列表
|
||||
*/
|
||||
@GET("/app/appMessage/list")
|
||||
suspend fun getMessage(): GetCodeBean<List<MessageGroup>>
|
||||
suspend fun getMessage(
|
||||
@Query("pageNum") pageNum: Int = 1,
|
||||
@Query("pageSize") pageSize: Int = 10
|
||||
): MessageListResponse
|
||||
|
||||
|
||||
/**
|
||||
@@ -216,6 +220,13 @@ interface ApiService {
|
||||
@POST("/app/upload")
|
||||
suspend fun uploadFile(@retrofit2.http.Part file: MultipartBody.Part): UploadResponse
|
||||
|
||||
/**
|
||||
* 查看告警消息
|
||||
*/
|
||||
//@GET("/app/appMessageInfo/{id}")
|
||||
//suspend fun getMessageInfo(@retrofit2.http.Path("id") id: String): GetCodeBean<MessageBean>
|
||||
|
||||
|
||||
/**
|
||||
* 修改家庭用户状态
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user