fix: some UI changes (for better or worse)

This commit is contained in:
aayush262 2024-03-08 00:45:13 +05:30
parent 7ac679f927
commit a2ca16355a
26 changed files with 493 additions and 444 deletions

View file

@ -1,48 +1,29 @@
package ani.dantotsu.profile
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
import ani.dantotsu.R
import ani.dantotsu.databinding.ActivityActivityBinding
import ani.dantotsu.databinding.ActivityFollowBinding
import ani.dantotsu.initActivity
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
class ActivityActivity : AppCompatActivity() {
private lateinit var binding: ActivityActivityBinding
private lateinit var binding: ActivityFollowBinding
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
val immersiveMode = PrefManager.getVal<Boolean>(PrefName.ImmersiveMode)
if (immersiveMode) {
requestWindowFeature(Window.FEATURE_NO_TITLE)
}
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
initActivity(this)
binding = ActivityActivityBinding.inflate(layoutInflater)
if (!immersiveMode) {
this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg_inv)
binding.root.fitsSystemWindows = true
} else {
binding.root.fitsSystemWindows = false
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
binding.listTitle.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = statusBarHeight
}
}
binding = ActivityFollowBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.listTitle.text = "Activity"
binding.listToolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = statusBarHeight }
binding.followerGrid.visibility = ViewGroup.GONE
binding.followerList.visibility = ViewGroup.GONE
}
}

View file

@ -2,23 +2,17 @@ package ani.dantotsu.profile
import android.content.Intent
import android.os.Bundle
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import android.view.Window
import android.view.WindowManager
import android.widget.ImageButton
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.User
import ani.dantotsu.databinding.ActivityFollowBinding
import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.statusBarHeight
@ -36,31 +30,11 @@ class FollowActivity : AppCompatActivity(){
private lateinit var selected: ImageButton
override fun onCreate(savedInstanceState: Bundle?) {
val immersiveMode = PrefManager.getVal<Boolean>(PrefName.ImmersiveMode)
if (immersiveMode) {
requestWindowFeature(Window.FEATURE_NO_TITLE)
}
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
initActivity(this)
binding = ActivityFollowBinding.inflate(layoutInflater)
if (!immersiveMode) {
this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg_inv)
binding.root.fitsSystemWindows = true
} else {
binding.root.fitsSystemWindows = false
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
binding.listTitle.updateLayoutParams<MarginLayoutParams> {
topMargin = statusBarHeight
}
}
binding.listToolbar.updateLayoutParams<MarginLayoutParams> { topMargin = statusBarHeight }
setContentView(binding.root)
val layoutType = PrefManager.getVal<Int>(PrefName.FollowerLayout)
selected = getSelected(layoutType)

View file

@ -1,10 +1,17 @@
package ani.dantotsu.profile
import android.app.Activity
import android.content.Context
import android.view.View
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemFollowerBinding
import ani.dantotsu.loadImage
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.request.RequestOptions
import com.xwray.groupie.viewbinding.BindableItem
import jp.wasabeef.glide.transformations.BlurTransformation
class FollowerItem(
private val id: Int,
@ -18,9 +25,16 @@ class FollowerItem(
override fun bind(viewBinding: ItemFollowerBinding, position: Int) {
binding = viewBinding
binding.profileUserName.text = name
val context = binding.profileBannerImage.context
avatar?.let { binding.profileUserAvatar.loadImage(it) }
if (banner != null) {
binding.profileBannerImage.loadImage(banner)
if (!(context as Activity).isDestroyed)
Glide.with(context as Context)
.load(GlideUrl(banner))
.diskCacheStrategy(DiskCacheStrategy.ALL).override(400)
.apply(RequestOptions.bitmapTransform(BlurTransformation(2, 6)))
.into(binding.profileBannerImage)
} else {
binding.profileBannerImage.setImageResource(R.drawable.linear_gradient_bg)
}

View file

@ -0,0 +1,79 @@
package ani.dantotsu.profile.activity
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.Notification
import ani.dantotsu.databinding.ActivityFollowBinding
import ani.dantotsu.initActivity
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.profile.ProfileActivity
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
import com.xwray.groupie.GroupieAdapter
import kotlinx.coroutines.launch
class NotificationActivity : AppCompatActivity() {
private lateinit var binding: ActivityFollowBinding
private var adapter: GroupieAdapter = GroupieAdapter()
private var notificationList: List<Notification> = emptyList()
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
initActivity(this)
binding = ActivityFollowBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.listTitle.text = "Notifications"
binding.listToolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = statusBarHeight }
binding.listRecyclerView.adapter = adapter
binding.listRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.followerGrid.visibility = ViewGroup.GONE
binding.followerList.visibility = ViewGroup.GONE
binding.listBack.setOnClickListener {
onBackPressed()
}
lifecycleScope.launch {
val res = Anilist.query.getNotifications(Anilist.userid?:0)
res?.data?.page?.notifications?.let { notifications ->
notificationList = notifications
adapter.update(notificationList.map { NotificationItem(it, ::onNotificationClick) })
}
}
}
private fun onNotificationClick(id: Int, type: NotificationClickType) {
when (type) {
NotificationClickType.USER -> {
ContextCompat.startActivity(
this, Intent(this, ProfileActivity::class.java)
.putExtra("userId", id), null
)
}
NotificationClickType.MEDIA -> {
ContextCompat.startActivity(
this, Intent(this, MediaDetailsActivity::class.java)
.putExtra("mediaId", id), null
)
}
NotificationClickType.UNDEFINED -> {
// Do nothing
}
}
}
companion object {
enum class NotificationClickType {
USER, MEDIA, UNDEFINED
}
}
}

View file

@ -1,13 +1,27 @@
package ani.dantotsu.profile.activity
import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import androidx.core.view.updateLayoutParams
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.api.Notification
import ani.dantotsu.connections.anilist.api.NotificationType
import ani.dantotsu.databinding.ItemNotificationBinding
import ani.dantotsu.loadImage
import ani.dantotsu.notifications.NotificationActivity
import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.statusBarHeight
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.request.RequestOptions
import com.xwray.groupie.viewbinding.BindableItem
import jp.wasabeef.glide.transformations.BlurTransformation
class NotificationItem(
private val notification: Notification,
@ -29,107 +43,133 @@ class NotificationItem(
return ItemNotificationBinding.bind(view)
}
private fun image(user: Boolean = false) {
val context = binding.notificationBannerImage.context
val cover = if (user) notification.user?.bannerImage else notification.media?.bannerImage
if (cover != null) {
if (!(context as Activity).isDestroyed)
Glide.with(context as Context)
.load(GlideUrl(cover))
.diskCacheStrategy(DiskCacheStrategy.ALL).override(400)
.apply(RequestOptions.bitmapTransform(BlurTransformation(2, 6)))
.into(binding.notificationBannerImage)
} else {
binding.notificationBannerImage.setImageResource(R.drawable.linear_gradient_bg)
}
if (user) {
binding.notificationCover.visibility = View.GONE
binding.notificationCoverUserContainer.visibility = View.VISIBLE
binding.notificationCoverUser.loadImage(notification.user?.avatar?.large)
val height = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80f, context.resources.displayMetrics).toInt()
binding.notificationBannerImage.layoutParams.height = height
binding.notificationBannerGradient.layoutParams.height = height
} else{
binding.notificationCoverUser.visibility = View.VISIBLE
binding.notificationCoverUserContainer.visibility = View.GONE
binding.notificationCover.loadImage(notification.media?.coverImage?.large)
}
}
private fun setBinding() {
val notificationType: NotificationType =
NotificationType.valueOf(notification.notificationType)
binding.notificationText.text = NotificationItemBuilder.getContent(notification)
binding.notificationDate.text = NotificationItemBuilder.getDateTime(notification.createdAt)
binding.root.setOnClickListener { clickCallback(id, clickType) }
when (notificationType) {
NotificationType.ACTIVITY_MESSAGE -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.ACTIVITY_REPLY -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.FOLLOWING -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.ACTIVITY_MENTION -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.THREAD_COMMENT_MENTION -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.THREAD_SUBSCRIBED -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.THREAD_COMMENT_REPLY -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.AIRING -> {
binding.notificationCover.loadImage(notification.media?.coverImage?.large)
binding.notificationBannerImage.loadImage(notification.media?.bannerImage)
image()
clickType = NotificationActivity.Companion.NotificationClickType.MEDIA
id = notification.media?.id ?: 0
}
NotificationType.ACTIVITY_LIKE -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.ACTIVITY_REPLY_LIKE -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.THREAD_LIKE -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.THREAD_COMMENT_LIKE -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.ACTIVITY_REPLY_SUBSCRIBED -> {
binding.notificationCover.loadImage(notification.user?.avatar?.large)
binding.notificationBannerImage.loadImage(notification.user?.bannerImage)
image(true)
clickType = NotificationActivity.Companion.NotificationClickType.USER
id = notification.user?.id ?: 0
}
NotificationType.RELATED_MEDIA_ADDITION -> {
binding.notificationCover.loadImage(notification.media?.coverImage?.large)
binding.notificationBannerImage.loadImage(notification.media?.bannerImage)
image()
clickType = NotificationActivity.Companion.NotificationClickType.MEDIA
id = notification.media?.id ?: 0
}
NotificationType.MEDIA_DATA_CHANGE -> {
binding.notificationCover.loadImage(notification.media?.coverImage?.large)
binding.notificationBannerImage.loadImage(notification.media?.bannerImage)
image()
clickType = NotificationActivity.Companion.NotificationClickType.MEDIA
id = notification.media?.id ?: 0
}
NotificationType.MEDIA_MERGE -> {
binding.notificationCover.loadImage(notification.media?.coverImage?.large)
binding.notificationBannerImage.loadImage(notification.media?.bannerImage)
image()
clickType = NotificationActivity.Companion.NotificationClickType.MEDIA
id = notification.media?.id ?: 0
}

View file

@ -138,11 +138,33 @@ interface NotificationItemBuilder {
}
}
fun getDateTime(time: Int): String {
val date = Date(time * 1000L)
val sdf = SimpleDateFormat("dd/MM/yyyy hh:mm a", Locale.getDefault())
return sdf.format(date)
}
fun getDateTime(timestamp: Int): String {
val targetDate = Date(timestamp * 1000L)
if (targetDate < Date(946684800000L)) { // January 1, 2000 (who want dates before that?)
return ""
}
val currentDate = Date()
val difference = currentDate.time - targetDate.time
return when (val daysDifference = difference / (1000 * 60 * 60 * 24)) {
0L -> {
val hoursDifference = difference / (1000 * 60 * 60)
val minutesDifference = (difference / (1000 * 60)) % 60
when {
hoursDifference > 0 -> "$hoursDifference hour${if (hoursDifference > 1) "s" else ""} ago"
minutesDifference > 0 -> "$minutesDifference minute${if (minutesDifference > 1) "s" else ""} ago"
else -> "Just now"
}
}
1L -> "1 day ago"
in 2..6 -> "$daysDifference days ago"
else -> SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(targetDate)
}
}
}
}