feat(notifications): Notification fetching & marking as read

This commit is contained in:
Peter Vacho 2025-01-04 12:35:45 +01:00
parent 4cf5a35255
commit dbbbfee769
Signed by: school
GPG key ID: 8CFC3837052871B4
2 changed files with 47 additions and 28 deletions

View file

@ -2,21 +2,29 @@ package com.p_vacho.neat_calendar.activities
import android.os.Bundle
import android.widget.ImageButton
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.p_vacho.neat_calendar.MyApplication
import com.p_vacho.neat_calendar.R
import com.p_vacho.neat_calendar.adapters.NotificationAdapter
import com.p_vacho.neat_calendar.api.RetrofitClient
import com.p_vacho.neat_calendar.api.models.NotificationResponse
import java.time.OffsetDateTime
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class NotificationsActivity : AppCompatActivity() {
private lateinit var rvNotifications: RecyclerView
private lateinit var btnBack: ImageButton
private lateinit var notifications: MutableList<NotificationResponse>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@ -31,33 +39,29 @@ class NotificationsActivity : AppCompatActivity() {
rvNotifications = findViewById(R.id.rvNotifications)
btnBack = findViewById(R.id.btnBack)
val notifications = fetchNotifications()
val adapter = NotificationAdapter(notifications, ::handleNotificationAction, ::handleNotificationClick)
rvNotifications.layoutManager = LinearLayoutManager(this)
rvNotifications.adapter = adapter
lifecycleScope.launch {
notifications = fetchNotifications().toMutableList()
rvNotifications.adapter = NotificationAdapter(notifications, ::handleNotificationAction, ::handleNotificationClick)
}
btnBack.setOnClickListener { finish() }
}
private fun fetchNotifications(): List<NotificationResponse> {
// TODO: Replace with actual API calls
return listOf(
NotificationResponse(
"1", "2", "invitation",
"You've been invited to event X",
"12", false, OffsetDateTime.now(), null
),
NotificationResponse(
"2", "2", "message",
"System maintenance scheduled",
"", false, OffsetDateTime.now(), null
),
NotificationResponse(
"2", "2", "message",
"App update available",
"", true, OffsetDateTime.now(), null
),
)
private suspend fun fetchNotifications(): List<NotificationResponse> {
val userId = (application as MyApplication).tokenManager.userId
if (userId == null) {
finish()
return emptyList()
}
val notifications = withContext(Dispatchers.IO) {
RetrofitClient.notificationsService.getUserNotifications(userId)
}
return notifications
}
private fun handleNotificationAction(notification: NotificationResponse, action: NotificationAdapter.Action, position: Int) {
@ -72,6 +76,15 @@ class NotificationsActivity : AppCompatActivity() {
}
private fun handleNotificationClick(notification: NotificationResponse, position: Int) {
TODO("Handle marking notification as read")
lifecycleScope.launch {
val updatedNotification =
RetrofitClient.notificationsService.markNotificationRead(notification.id)
notifications[position] = updatedNotification
val adapter = rvNotifications.adapter as NotificationAdapter
adapter.notifyItemChanged(position)
Toast.makeText(this@NotificationsActivity, "Marked as read", Toast.LENGTH_SHORT).show()
}
}
}

View file

@ -10,7 +10,7 @@ import com.p_vacho.neat_calendar.R
import com.p_vacho.neat_calendar.api.models.NotificationResponse
class NotificationAdapter(
private val notifications: List<NotificationResponse>,
private val notifications: MutableList<NotificationResponse>,
private val onActionClick: (NotificationResponse, Action, Int) -> Unit,
private val onNotificationClick: (NotificationResponse, Int) -> Unit,
) : RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder>() {
@ -54,9 +54,15 @@ class NotificationAdapter(
holder.invitationActions.visibility = View.GONE
}
// Set click listener for the whole notification (excluding buttons)
holder.itemView.setOnClickListener {
onNotificationClick(notification, position)
// Set click listener for the whole notification (only for unread ones though)
if (!notification.read) {
holder.itemView.isClickable = true
holder.itemView.setOnClickListener {
onNotificationClick(notification, position)
}
} else {
holder.itemView.isClickable = false
holder.itemView.setOnClickListener(null)
}
// Ensure buttons consume their click events