PixelDroid-App-Android/app/src/main/java/com/h/pixeldroid/posts/feeds/cachedFeeds/notifications/NotificationsFragment.kt

261 lines
9.1 KiB
Kotlin
Raw Normal View History

package com.h.pixeldroid.posts.feeds.cachedFeeds.notifications
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
2020-12-29 22:14:32 +01:00
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.ViewModelProvider
2020-12-29 22:14:32 +01:00
import androidx.lifecycle.lifecycleScope
import androidx.paging.ExperimentalPagingApi
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.h.pixeldroid.R
import com.h.pixeldroid.databinding.FragmentNotificationsBinding
import com.h.pixeldroid.posts.PostActivity
import com.h.pixeldroid.posts.feeds.cachedFeeds.CachedFeedFragment
import com.h.pixeldroid.posts.feeds.cachedFeeds.FeedViewModel
import com.h.pixeldroid.posts.feeds.cachedFeeds.ViewModelFactory
import com.h.pixeldroid.posts.parseHTMLText
import com.h.pixeldroid.posts.setTextViewFromISO8601
import com.h.pixeldroid.profile.ProfileActivity
import com.h.pixeldroid.utils.api.objects.Account
import com.h.pixeldroid.utils.api.objects.Notification
import com.h.pixeldroid.utils.api.objects.Status
import com.h.pixeldroid.utils.di.PixelfedAPIHolder
/**
* Fragment for the notifications tab.
*/
class NotificationsFragment : CachedFeedFragment<Notification>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
adapter = NotificationsAdapter(apiHolder)
}
@ExperimentalPagingApi
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = super.onCreateView(inflater, container, savedInstanceState)
// get the view model
@Suppress("UNCHECKED_CAST")
2020-12-29 22:14:32 +01:00
viewModel = ViewModelProvider(
this,
ViewModelFactory(db, db.notificationDao(), NotificationsRemoteMediator(apiHolder, db))
)
.get(FeedViewModel::class.java) as FeedViewModel<Notification>
launch()
initSearch()
return view
}
2020-12-29 22:14:32 +01:00
/**
* View Holder for a [Notification] RecyclerView list item.
*/
class NotificationViewHolder(binding: FragmentNotificationsBinding) : RecyclerView.ViewHolder(binding.root) {
private val notificationType: TextView = binding.notificationType
private val notificationTime: TextView = binding.notificationTime
private val postDescription: TextView = binding.notificationPostDescription
private val avatar: ImageView = binding.notificationAvatar
private val photoThumbnail: ImageView = binding.notificationPhotoThumbnail
2020-12-29 22:14:32 +01:00
private var notification: Notification? = null
2020-12-29 22:14:32 +01:00
init {
itemView.setOnClickListener {
notification?.openActivity()
}
}
2020-12-29 22:14:32 +01:00
private fun Notification.openActivity() {
val intent: Intent =
when (type) {
Notification.NotificationType.mention, Notification.NotificationType.favourite,
Notification.NotificationType.poll, Notification.NotificationType.reblog -> {
openPostFromNotification()
}
Notification.NotificationType.follow -> {
Intent(itemView.context, ProfileActivity::class.java).apply {
putExtra(Account.ACCOUNT_TAG, account)
}
}
null -> return //TODO show an error here?
}
2020-12-29 22:14:32 +01:00
itemView.context.startActivity(intent)
}
2020-12-29 22:14:32 +01:00
private fun Notification.openPostFromNotification(): Intent =
Intent(itemView.context, PostActivity::class.java).apply {
putExtra(Status.POST_TAG, status)
}
2020-12-29 22:14:32 +01:00
private fun setNotificationType(
type: Notification.NotificationType,
username: String,
textView: TextView
) {
val context = textView.context
val (format: String, drawable: Drawable?) = when (type) {
Notification.NotificationType.follow -> {
getStringAndDrawable(
context,
R.string.followed_notification,
R.drawable.ic_follow
)
}
Notification.NotificationType.mention -> {
getStringAndDrawable(
context,
R.string.mention_notification,
R.drawable.mention_at_24dp
)
}
2020-12-29 22:14:32 +01:00
Notification.NotificationType.reblog -> {
getStringAndDrawable(
context,
R.string.shared_notification,
R.drawable.ic_reblog_blue
)
}
2020-12-29 22:14:32 +01:00
Notification.NotificationType.favourite -> {
getStringAndDrawable(
context,
R.string.liked_notification,
R.drawable.ic_like_full
)
}
Notification.NotificationType.poll -> {
getStringAndDrawable(context, R.string.poll_notification, R.drawable.poll)
}
}
2020-12-29 22:14:32 +01:00
textView.text = format.format(username)
textView.setCompoundDrawablesWithIntrinsicBounds(
drawable, null, null, null
)
}
2020-12-29 22:14:32 +01:00
private fun getStringAndDrawable(
context: Context,
stringToFormat: Int,
drawable: Int
): Pair<String, Drawable?> =
Pair(context.getString(stringToFormat), ContextCompat.getDrawable(context, drawable))
2020-12-29 22:14:32 +01:00
fun bind(
notification: Notification?,
api: PixelfedAPIHolder,
lifecycleScope: LifecycleCoroutineScope,
2020-12-29 22:14:32 +01:00
) {
2020-12-29 22:14:32 +01:00
this.notification = notification
2020-12-29 22:14:32 +01:00
Glide.with(itemView).load(notification?.account?.avatar_static).circleCrop()
.into(avatar)
2020-12-29 22:14:32 +01:00
val previewUrl = notification?.status?.media_attachments?.getOrNull(0)?.preview_url
if (!previewUrl.isNullOrBlank()) {
Glide.with(itemView).load(previewUrl)
.placeholder(R.drawable.ic_picture_fallback).into(photoThumbnail)
} else {
photoThumbnail.visibility = View.GONE
}
2020-12-29 22:14:32 +01:00
notification?.type?.let {
notification.account?.username?.let { username ->
setNotificationType(
it,
username,
notificationType
)
}
}
notification?.created_at?.let {
setTextViewFromISO8601(
it,
notificationTime,
false,
itemView.context
)
}
2020-12-29 22:14:32 +01:00
//Convert HTML to clickable text
postDescription.text =
parseHTMLText(
notification?.status?.content ?: "",
notification?.status?.mentions,
api,
itemView.context,
lifecycleScope
2020-12-29 22:14:32 +01:00
)
}
companion object {
fun create(parent: ViewGroup): NotificationViewHolder {
val itemBinding = FragmentNotificationsBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return NotificationViewHolder(itemBinding)
2020-12-29 22:14:32 +01:00
}
}
}
2020-12-29 22:14:32 +01:00
inner class NotificationsAdapter(
private val apiHolder: PixelfedAPIHolder,
) : PagingDataAdapter<Notification, RecyclerView.ViewHolder>(
object : DiffUtil.ItemCallback<Notification>() {
override fun areItemsTheSame(
oldItem: Notification,
newItem: Notification
): Boolean {
return oldItem.id == newItem.id
}
2020-12-29 22:14:32 +01:00
override fun areContentsTheSame(
oldItem: Notification,
newItem: Notification
): Boolean =
oldItem == newItem
}
) {
2020-12-29 22:14:32 +01:00
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return NotificationViewHolder.create(parent)
}
2020-12-29 22:14:32 +01:00
override fun getItemViewType(position: Int): Int {
return R.layout.fragment_notifications
}
2020-12-29 22:14:32 +01:00
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val uiModel = getItem(position)
uiModel.let {
(holder as NotificationViewHolder).bind(
it,
apiHolder,
lifecycleScope
2020-12-29 22:14:32 +01:00
)
}
}
}
}