feat: global/personal feed | like posts | pagination
This commit is contained in:
parent
a9b03c45c6
commit
98f4d4f30b
19 changed files with 438 additions and 144 deletions
|
@ -115,7 +115,7 @@
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden"
|
android:windowSoftInputMode="adjustResize|stateHidden"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:parentActivityName=".MainActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".profile.activity.ActivityActivity"
|
android:name=".profile.activity.FeedActivity"
|
||||||
android:label="Inbox Activity"
|
android:label="Inbox Activity"
|
||||||
android:parentActivityName=".MainActivity" >
|
android:parentActivityName=".MainActivity" >
|
||||||
</activity>
|
</activity>
|
||||||
|
|
|
@ -28,6 +28,7 @@ import android.telephony.TelephonyManager
|
||||||
import android.text.InputFilter
|
import android.text.InputFilter
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
@ -129,7 +130,8 @@ var loadIsMAL = false
|
||||||
|
|
||||||
fun logger(e: Any?, print: Boolean = true) {
|
fun logger(e: Any?, print: Boolean = true) {
|
||||||
if (print)
|
if (print)
|
||||||
println(e)
|
//println(e)
|
||||||
|
Log.d("Logger", e.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ import ani.dantotsu.connections.anilist.Anilist.authorRoles
|
||||||
import ani.dantotsu.connections.anilist.Anilist.executeQuery
|
import ani.dantotsu.connections.anilist.Anilist.executeQuery
|
||||||
import ani.dantotsu.connections.anilist.api.FeedResponse
|
import ani.dantotsu.connections.anilist.api.FeedResponse
|
||||||
import ani.dantotsu.connections.anilist.api.FuzzyDate
|
import ani.dantotsu.connections.anilist.api.FuzzyDate
|
||||||
import ani.dantotsu.connections.anilist.api.Notification
|
|
||||||
import ani.dantotsu.connections.anilist.api.NotificationResponse
|
import ani.dantotsu.connections.anilist.api.NotificationResponse
|
||||||
import ani.dantotsu.connections.anilist.api.Page
|
import ani.dantotsu.connections.anilist.api.Page
|
||||||
import ani.dantotsu.connections.anilist.api.Query
|
import ani.dantotsu.connections.anilist.api.Query
|
||||||
|
import ani.dantotsu.connections.anilist.api.ToggleLike
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.isOnline
|
import ani.dantotsu.isOnline
|
||||||
import ani.dantotsu.logError
|
import ani.dantotsu.logError
|
||||||
|
@ -1265,10 +1265,15 @@ Page(page:$page,perPage:50) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun toggleFollow(id: Int): Query.ToggleFollow? {
|
suspend fun toggleFollow(id: Int): Query.ToggleFollow? {
|
||||||
val response = executeQuery<Query.ToggleFollow>(
|
return executeQuery<Query.ToggleFollow>(
|
||||||
"""mutation{ToggleFollow(userId:$id){id, isFollowing, isFollower}}"""
|
"""mutation{ToggleFollow(userId:$id){id, isFollowing, isFollower}}"""
|
||||||
)
|
)
|
||||||
return response
|
}
|
||||||
|
|
||||||
|
suspend fun toggleLike(id: Int, type: String): ToggleLike? {
|
||||||
|
return executeQuery<ToggleLike>(
|
||||||
|
"""mutation Like{ToggleLikeV2(id:$id,type:$type){__typename}}"""
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getUserProfile(id: Int): Query.UserProfileResponse? {
|
suspend fun getUserProfile(id: Int): Query.UserProfileResponse? {
|
||||||
|
@ -1342,8 +1347,8 @@ Page(page:$page,perPage:50) {
|
||||||
return default
|
return default
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getNotifications(id: Int): NotificationResponse? {
|
suspend fun getNotifications(id: Int, page: Int = 1): NotificationResponse? {
|
||||||
val res = executeQuery<NotificationResponse>("""{User(id:$id){unreadNotificationCount}Page{notifications(resetNotificationCount:true){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""", force = true)
|
val res = executeQuery<NotificationResponse>("""{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){notifications(resetNotificationCount:true){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""", force = true)
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
Anilist.unreadNotificationCount = 0
|
Anilist.unreadNotificationCount = 0
|
||||||
}
|
}
|
||||||
|
@ -1354,7 +1359,11 @@ Page(page:$page,perPage:50) {
|
||||||
val filter = if (userId != null) "userId:$userId,"
|
val filter = if (userId != null) "userId:$userId,"
|
||||||
else if (global) "isFollowing:false,"
|
else if (global) "isFollowing:false,"
|
||||||
else "isFollowing:true,"
|
else "isFollowing:true,"
|
||||||
val res = executeQuery<FeedResponse>("""{Page(page:$page,perPage:25){activities(${filter}sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id title{english romaji native userPreferred}bannerImage coverImage{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id recipientId messengerId type replyCount message(asHtml:true)isLocked isSubscribed isLiked isPrivate siteUrl createdAt recipient{id name bannerImage avatar{medium large}}messenger{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}}}}""")
|
val res = executeQuery<FeedResponse>("""{Page(page:$page,perPage:$ITEMS_PER_PAGE){activities(${filter}sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id title{english romaji native userPreferred}bannerImage coverImage{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id recipientId messengerId type replyCount message(asHtml:true)isLocked isSubscribed isLiked isPrivate siteUrl createdAt recipient{id name bannerImage avatar{medium large}}messenger{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}}}}""")
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ITEMS_PER_PAGE = 25
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,19 +7,19 @@ import kotlinx.serialization.Serializable
|
||||||
data class FeedResponse(
|
data class FeedResponse(
|
||||||
@SerialName("data")
|
@SerialName("data")
|
||||||
val data: Data
|
val data: Data
|
||||||
) {
|
) : java.io.Serializable {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Data(
|
data class Data(
|
||||||
@SerialName("Page")
|
@SerialName("Page")
|
||||||
val page: ActivityPage
|
val page: ActivityPage
|
||||||
)
|
) : java.io.Serializable
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ActivityPage(
|
data class ActivityPage(
|
||||||
@SerialName("activities")
|
@SerialName("activities")
|
||||||
val activities: List<Activity>
|
val activities: List<Activity>
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Activity(
|
data class Activity(
|
||||||
|
@ -52,9 +52,9 @@ data class Activity(
|
||||||
@SerialName("isSubscribed")
|
@SerialName("isSubscribed")
|
||||||
val isSubscribed: Boolean,
|
val isSubscribed: Boolean,
|
||||||
@SerialName("likeCount")
|
@SerialName("likeCount")
|
||||||
val likeCount: Int?,
|
var likeCount: Int?,
|
||||||
@SerialName("isLiked")
|
@SerialName("isLiked")
|
||||||
val isLiked: Boolean?,
|
var isLiked: Boolean?,
|
||||||
@SerialName("isPinned")
|
@SerialName("isPinned")
|
||||||
val isPinned: Boolean?,
|
val isPinned: Boolean?,
|
||||||
@SerialName("isPrivate")
|
@SerialName("isPrivate")
|
||||||
|
@ -69,7 +69,7 @@ data class Activity(
|
||||||
val replies: List<Reply>?,
|
val replies: List<Reply>?,
|
||||||
@SerialName("likes")
|
@SerialName("likes")
|
||||||
val likes: List<User>?,
|
val likes: List<User>?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Reply(
|
data class Reply(
|
||||||
|
@ -89,4 +89,22 @@ data class Reply(
|
||||||
val user: User,
|
val user: User,
|
||||||
@SerialName("likes")
|
@SerialName("likes")
|
||||||
val likes: List<User>?,
|
val likes: List<User>?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ToggleLike(
|
||||||
|
@SerialName("data")
|
||||||
|
val data: Data
|
||||||
|
) : java.io.Serializable {
|
||||||
|
@Serializable
|
||||||
|
data class Data(
|
||||||
|
@SerialName("ToggleLikeV2")
|
||||||
|
val toggleLike: LikeData
|
||||||
|
) : java.io.Serializable
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class LikeData(
|
||||||
|
@SerialName("__typename")
|
||||||
|
val typename: String
|
||||||
|
) : java.io.Serializable
|
|
@ -14,6 +14,7 @@ import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.api.User
|
import ani.dantotsu.connections.anilist.api.User
|
||||||
import ani.dantotsu.databinding.ActivityFollowBinding
|
import ani.dantotsu.databinding.ActivityFollowBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
|
@ -36,6 +37,7 @@ class FollowActivity : AppCompatActivity(){
|
||||||
initActivity(this)
|
initActivity(this)
|
||||||
binding = ActivityFollowBinding.inflate(layoutInflater)
|
binding = ActivityFollowBinding.inflate(layoutInflater)
|
||||||
binding.listToolbar.updateLayoutParams<MarginLayoutParams> { topMargin = statusBarHeight }
|
binding.listToolbar.updateLayoutParams<MarginLayoutParams> { topMargin = statusBarHeight }
|
||||||
|
binding.listFrameLayout.updateLayoutParams<MarginLayoutParams> { bottomMargin = navBarHeight }
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
val layoutType = PrefManager.getVal<Int>(PrefName.FollowerLayout)
|
val layoutType = PrefManager.getVal<Int>(PrefName.FollowerLayout)
|
||||||
selected = getSelected(layoutType)
|
selected = getSelected(layoutType)
|
||||||
|
|
|
@ -22,7 +22,7 @@ import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
import ani.dantotsu.others.ImageViewDialog
|
import ani.dantotsu.others.ImageViewDialog
|
||||||
import ani.dantotsu.profile.activity.ActivityActivity
|
import ani.dantotsu.profile.activity.FeedFragment
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
|
@ -36,8 +36,8 @@ import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
|
|
||||||
|
|
||||||
class ProfileActivity : AppCompatActivity() {
|
class ProfileActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityProfileBinding
|
lateinit var binding: ActivityProfileBinding
|
||||||
private var selected: Int = 0
|
private var selected: Int = 1
|
||||||
private lateinit var navBar: AnimatedBottomBar
|
private lateinit var navBar: AnimatedBottomBar
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
|
@ -49,8 +49,10 @@ class ProfileActivity : AppCompatActivity() {
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
navBar = binding.profileNavBar
|
navBar = binding.profileNavBar
|
||||||
navBar.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin = navBarHeight }
|
navBar.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin = navBarHeight }
|
||||||
|
val feedTab = navBar.createTab(R.drawable.ic_round_filter_24, "Feed")
|
||||||
val profileTab = navBar.createTab(R.drawable.ic_round_person_24, "Profile")
|
val profileTab = navBar.createTab(R.drawable.ic_round_person_24, "Profile")
|
||||||
val statsTab = navBar.createTab(R.drawable.ic_stats_24, "Stats")
|
val statsTab = navBar.createTab(R.drawable.ic_stats_24, "Stats")
|
||||||
|
navBar.addTab(feedTab)
|
||||||
navBar.addTab(profileTab)
|
navBar.addTab(profileTab)
|
||||||
navBar.addTab(statsTab)
|
navBar.addTab(statsTab)
|
||||||
navBar.visibility = View.GONE
|
navBar.visibility = View.GONE
|
||||||
|
@ -70,6 +72,7 @@ class ProfileActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
binding.profileViewPager.adapter =
|
binding.profileViewPager.adapter =
|
||||||
ViewPagerAdapter(supportFragmentManager, lifecycle, user)
|
ViewPagerAdapter(supportFragmentManager, lifecycle, user)
|
||||||
|
binding.profileViewPager.setCurrentItem(selected, false)
|
||||||
navBar.visibility = View.VISIBLE
|
navBar.visibility = View.VISIBLE
|
||||||
navBar.selectTabAt(selected)
|
navBar.selectTabAt(selected)
|
||||||
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {
|
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {
|
||||||
|
@ -106,15 +109,6 @@ class ProfileActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
binding.profileProgressBar.visibility = View.GONE
|
binding.profileProgressBar.visibility = View.GONE
|
||||||
binding.profileTopContainer.visibility = View.VISIBLE
|
binding.profileTopContainer.visibility = View.VISIBLE
|
||||||
binding.profileActivityButton.setOnClickListener {
|
|
||||||
ContextCompat.startActivity(
|
|
||||||
this@ProfileActivity,
|
|
||||||
Intent(this@ProfileActivity, ActivityActivity::class.java)
|
|
||||||
.putExtra("userId", user.id)
|
|
||||||
.putExtra("username", user.name),
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
binding.profileMenuButton.setOnClickListener {
|
binding.profileMenuButton.setOnClickListener {
|
||||||
val popup = PopupMenu(this@ProfileActivity, binding.profileMenuButton)
|
val popup = PopupMenu(this@ProfileActivity, binding.profileMenuButton)
|
||||||
popup.menuInflater.inflate(R.menu.menu_profile, popup.menu)
|
popup.menuInflater.inflate(R.menu.menu_profile, popup.menu)
|
||||||
|
@ -161,7 +155,6 @@ class ProfileActivity : AppCompatActivity() {
|
||||||
binding.profileBannerImage.updateLayoutParams { height += statusBarHeight }
|
binding.profileBannerImage.updateLayoutParams { height += statusBarHeight }
|
||||||
binding.profileBannerGradient.updateLayoutParams { height += statusBarHeight }
|
binding.profileBannerGradient.updateLayoutParams { height += statusBarHeight }
|
||||||
binding.profileMenuButton.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }
|
binding.profileMenuButton.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }
|
||||||
binding.profileActivityButton.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }
|
|
||||||
binding.profileBannerImage.setOnLongClickListener {
|
binding.profileBannerImage.setOnLongClickListener {
|
||||||
ImageViewDialog.newInstance(
|
ImageViewDialog.newInstance(
|
||||||
this@ProfileActivity,
|
this@ProfileActivity,
|
||||||
|
@ -188,10 +181,11 @@ class ProfileActivity : AppCompatActivity() {
|
||||||
) :
|
) :
|
||||||
FragmentStateAdapter(fragmentManager, lifecycle) {
|
FragmentStateAdapter(fragmentManager, lifecycle) {
|
||||||
|
|
||||||
override fun getItemCount(): Int = 2
|
override fun getItemCount(): Int = 3
|
||||||
override fun createFragment(position: Int): Fragment = when (position) {
|
override fun createFragment(position: Int): Fragment = when (position) {
|
||||||
0 -> ProfileFragment.newInstance(user)
|
0 -> FeedFragment.newInstance(user.id, false)
|
||||||
1 -> StatsFragment.newInstance(user)
|
1 -> ProfileFragment.newInstance(user)
|
||||||
|
2 -> StatsFragment.newInstance(user)
|
||||||
else -> ProfileFragment.newInstance(user)
|
else -> ProfileFragment.newInstance(user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
class ProfileFragment() : Fragment() {
|
class ProfileFragment : Fragment() {
|
||||||
lateinit var binding: FragmentProfileBinding
|
lateinit var binding: FragmentProfileBinding
|
||||||
private lateinit var activity: ProfileActivity
|
private lateinit var activity: ProfileActivity
|
||||||
private lateinit var user: Query.UserProfile
|
private lateinit var user: Query.UserProfile
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
package ani.dantotsu.profile.activity
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
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.Activity
|
|
||||||
import ani.dantotsu.databinding.ActivityFollowBinding
|
|
||||||
import ani.dantotsu.initActivity
|
|
||||||
import ani.dantotsu.statusBarHeight
|
|
||||||
import ani.dantotsu.themes.ThemeManager
|
|
||||||
import com.xwray.groupie.GroupieAdapter
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class ActivityActivity : AppCompatActivity() {
|
|
||||||
private lateinit var binding: ActivityFollowBinding
|
|
||||||
private var adapter: GroupieAdapter = GroupieAdapter()
|
|
||||||
private var activityList: List<Activity> = 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 = "Activity"
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
binding.listProgressBar.visibility = ViewGroup.VISIBLE
|
|
||||||
var userId: Int? = intent.getIntExtra("userId", -1)
|
|
||||||
if (userId == -1) userId = null
|
|
||||||
val global = intent.getBooleanExtra("global", false)
|
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
val res = Anilist.query.getFeed(userId, global)
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main){
|
|
||||||
res?.data?.page?.activities?.let { activities ->
|
|
||||||
activityList = activities
|
|
||||||
adapter.update(activityList.map { ActivityItem(it){} })
|
|
||||||
}
|
|
||||||
binding.listProgressBar.visibility = ViewGroup.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,21 +6,29 @@ import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.buildMarkwon
|
import ani.dantotsu.buildMarkwon
|
||||||
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.api.Activity
|
import ani.dantotsu.connections.anilist.api.Activity
|
||||||
import ani.dantotsu.databinding.ItemActivityBinding
|
import ani.dantotsu.databinding.ItemActivityBinding
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
|
import ani.dantotsu.snackString
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
import com.bumptech.glide.load.model.GlideUrl
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.xwray.groupie.viewbinding.BindableItem
|
import com.xwray.groupie.viewbinding.BindableItem
|
||||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class ActivityItem(
|
class ActivityItem(
|
||||||
private val activity: Activity,
|
private val activity: Activity,
|
||||||
val clickCallback: (Int) -> Unit
|
val clickCallback: (Int, type: String) -> Unit
|
||||||
): BindableItem<ItemActivityBinding>() {
|
) : BindableItem<ItemActivityBinding>() {
|
||||||
private lateinit var binding: ItemActivityBinding
|
private lateinit var binding: ItemActivityBinding
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun bind(viewBinding: ItemActivityBinding, position: Int) {
|
override fun bind(viewBinding: ItemActivityBinding, position: Int) {
|
||||||
binding = viewBinding
|
binding = viewBinding
|
||||||
|
@ -28,24 +36,48 @@ class ActivityItem(
|
||||||
binding.activityUserName.text = activity.user?.name
|
binding.activityUserName.text = activity.user?.name
|
||||||
binding.activityUserAvatar.loadImage(activity.user?.avatar?.medium)
|
binding.activityUserAvatar.loadImage(activity.user?.avatar?.medium)
|
||||||
binding.activityTime.text = ActivityItemBuilder.getDateTime(activity.createdAt)
|
binding.activityTime.text = ActivityItemBuilder.getDateTime(activity.createdAt)
|
||||||
val color = if (activity.isLiked == true)
|
val likeColor = ContextCompat.getColor(binding.root.context, R.color.yt_red)
|
||||||
ContextCompat.getColor(binding.root.context, R.color.yt_red)
|
val notLikeColor = ContextCompat.getColor(binding.root.context, R.color.bg_opp)
|
||||||
else
|
binding.activityLike.setColorFilter(if (activity.isLiked == true) likeColor else notLikeColor)
|
||||||
ContextCompat.getColor(binding.root.context, R.color.bg_opp)
|
binding.commentRepliesContainer.visibility =
|
||||||
binding.activityFavorite.setColorFilter(color)
|
if (activity.replyCount > 0) View.VISIBLE else View.GONE
|
||||||
binding.commentRepliesContainer.visibility = if (activity.replyCount > 0) View.VISIBLE else View.GONE
|
binding.activityLikeCount.text = activity.likeCount.toString()
|
||||||
|
|
||||||
|
binding.activityLike.setOnClickListener {
|
||||||
|
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||||
|
scope.launch {
|
||||||
|
val res = Anilist.query.toggleLike(activity.id, "ACTIVITY")
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (res != null) {
|
||||||
|
|
||||||
|
if (activity.isLiked == true) {
|
||||||
|
activity.likeCount = activity.likeCount?.minus(1)
|
||||||
|
} else {
|
||||||
|
activity.likeCount = activity.likeCount?.plus(1)
|
||||||
|
}
|
||||||
|
binding.activityLikeCount.text = activity.likeCount.toString()
|
||||||
|
activity.isLiked = !activity.isLiked!!
|
||||||
|
binding.activityLike.setColorFilter(if (activity.isLiked == true) likeColor else notLikeColor)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
snackString("Failed to like activity")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val context = binding.root.context
|
val context = binding.root.context
|
||||||
|
|
||||||
when (activity.typename) {
|
when (activity.typename) {
|
||||||
"ListActivity" ->{
|
"ListActivity" -> {
|
||||||
binding.activityContent.visibility = View.GONE
|
binding.activityContent.visibility = View.GONE
|
||||||
binding.activityBannerContainer.visibility = View.VISIBLE
|
binding.activityBannerContainer.visibility = View.VISIBLE
|
||||||
|
|
||||||
binding.activityMediaName.text = activity.media?.title?.userPreferred
|
binding.activityMediaName.text = activity.media?.title?.userPreferred
|
||||||
binding.activityText.text = "${activity.user!!.name} ${activity.status} ${activity.media!!.title!!.userPreferred}"
|
binding.activityText.text =
|
||||||
binding.activityCover.loadImage(activity.media.coverImage?.medium)
|
"""${activity.user!!.name} ${activity.status} ${activity.progress ?: ""}"""
|
||||||
val banner = activity.media.bannerImage
|
binding.activityCover.loadImage(activity.media?.coverImage?.medium)
|
||||||
|
val banner = activity.media?.bannerImage
|
||||||
if (banner != null) {
|
if (banner != null) {
|
||||||
if (!(context as android.app.Activity).isDestroyed) {
|
if (!(context as android.app.Activity).isDestroyed) {
|
||||||
Glide.with(context as Context)
|
Glide.with(context as Context)
|
||||||
|
@ -58,6 +90,7 @@ class ActivityItem(
|
||||||
binding.activityBannerImage.setImageResource(R.drawable.linear_gradient_bg)
|
binding.activityBannerImage.setImageResource(R.drawable.linear_gradient_bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"TextActivity" -> {
|
"TextActivity" -> {
|
||||||
binding.activityBannerContainer.visibility = View.GONE
|
binding.activityBannerContainer.visibility = View.GONE
|
||||||
binding.activityContent.visibility = View.VISIBLE
|
binding.activityContent.visibility = View.VISIBLE
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package ani.dantotsu.profile.activity
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.databinding.ActivityFeedBinding
|
||||||
|
import ani.dantotsu.initActivity
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.statusBarHeight
|
||||||
|
import ani.dantotsu.themes.ThemeManager
|
||||||
|
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
|
|
||||||
|
class FeedActivity: AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityFeedBinding
|
||||||
|
private var selected: Int = 0
|
||||||
|
private lateinit var navBar: AnimatedBottomBar
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
ThemeManager(this).applyTheme()
|
||||||
|
initActivity(this)
|
||||||
|
binding = ActivityFeedBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
navBar = binding.feedNavBar
|
||||||
|
navBar.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin += navBarHeight }
|
||||||
|
val personalTab = navBar.createTab(R.drawable.ic_round_person_24, "Personal")
|
||||||
|
val globalTab = navBar.createTab(R.drawable.ic_globe_24, "Global")
|
||||||
|
navBar.addTab(personalTab)
|
||||||
|
navBar.addTab(globalTab)
|
||||||
|
binding.listTitle.text = "Activities"
|
||||||
|
binding.feedViewPager.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
bottomMargin += navBarHeight
|
||||||
|
topMargin += statusBarHeight
|
||||||
|
}
|
||||||
|
binding.listToolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }
|
||||||
|
binding.feedViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle)
|
||||||
|
binding.feedViewPager.setCurrentItem(selected, false)
|
||||||
|
binding.feedViewPager.isUserInputEnabled = false
|
||||||
|
navBar.selectTabAt(selected)
|
||||||
|
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {
|
||||||
|
override fun onTabSelected(
|
||||||
|
lastIndex: Int,
|
||||||
|
lastTab: AnimatedBottomBar.Tab?,
|
||||||
|
newIndex: Int,
|
||||||
|
newTab: AnimatedBottomBar.Tab
|
||||||
|
) {
|
||||||
|
selected = newIndex
|
||||||
|
binding.feedViewPager.setCurrentItem(selected, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
binding.listBack.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
navBar.selectTabAt(selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ViewPagerAdapter(
|
||||||
|
fragmentManager: FragmentManager,
|
||||||
|
lifecycle: Lifecycle
|
||||||
|
) : FragmentStateAdapter(fragmentManager, lifecycle) {
|
||||||
|
override fun getItemCount(): Int = 2
|
||||||
|
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return when (position) {
|
||||||
|
0 -> FeedFragment.newInstance(null, false)
|
||||||
|
else -> FeedFragment.newInstance(null, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt
Normal file
111
app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
package ani.dantotsu.profile.activity
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
|
import ani.dantotsu.connections.anilist.AnilistQueries
|
||||||
|
import ani.dantotsu.connections.anilist.api.Activity
|
||||||
|
import ani.dantotsu.databinding.FragmentFeedBinding
|
||||||
|
import ani.dantotsu.logger
|
||||||
|
import ani.dantotsu.profile.ProfileActivity
|
||||||
|
import ani.dantotsu.snackString
|
||||||
|
import com.xwray.groupie.GroupieAdapter
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class FeedFragment : Fragment() {
|
||||||
|
private lateinit var binding: FragmentFeedBinding
|
||||||
|
private var adapter: GroupieAdapter = GroupieAdapter()
|
||||||
|
private var activityList: List<Activity> = emptyList()
|
||||||
|
private lateinit var activity: androidx.activity.ComponentActivity
|
||||||
|
private var page: Int = 1
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
binding = FragmentFeedBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
activity = requireActivity()
|
||||||
|
binding.listRecyclerView.adapter = adapter
|
||||||
|
binding.listRecyclerView.layoutManager =
|
||||||
|
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding.listProgressBar.visibility = ViewGroup.VISIBLE
|
||||||
|
var userId: Int? = arguments?.getInt("userId", -1)
|
||||||
|
if (userId == -1) userId = null
|
||||||
|
val global = arguments?.getBoolean("global", false) ?: false
|
||||||
|
|
||||||
|
activity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val res = Anilist.query.getFeed(userId, global)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
res?.data?.page?.activities?.let { activities ->
|
||||||
|
activityList = activities
|
||||||
|
adapter.update(activityList.map { ActivityItem(it) { _, _ -> } })
|
||||||
|
}
|
||||||
|
binding.listProgressBar.visibility = ViewGroup.GONE
|
||||||
|
val scrollView = if (activity is ProfileActivity) {
|
||||||
|
(activity as ProfileActivity).binding.profileScrollView
|
||||||
|
} else {
|
||||||
|
binding.listRecyclerView
|
||||||
|
}
|
||||||
|
binding.listRecyclerView.setOnTouchListener { _, event ->
|
||||||
|
if (event?.action == MotionEvent.ACTION_UP) {
|
||||||
|
if (adapter.itemCount % AnilistQueries.ITEMS_PER_PAGE != 0) {
|
||||||
|
snackString("No more activities")
|
||||||
|
} else if (!scrollView.canScrollVertically(1) && !binding.feedRefresh.isVisible
|
||||||
|
&& binding.listRecyclerView.adapter!!.itemCount != 0 &&
|
||||||
|
(binding.listRecyclerView.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() == (binding.listRecyclerView.adapter!!.itemCount - 1)
|
||||||
|
) {
|
||||||
|
page++
|
||||||
|
binding.feedRefresh.visibility = ViewGroup.VISIBLE
|
||||||
|
activity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val res = Anilist.query.getFeed(userId, global, page)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
res?.data?.page?.activities?.let { activities ->
|
||||||
|
activityList += activities
|
||||||
|
adapter.addAll(activities.map { ActivityItem(it) { _, _ -> } })
|
||||||
|
}
|
||||||
|
binding.feedRefresh.visibility = ViewGroup.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (this::binding.isInitialized) {
|
||||||
|
binding.root.requestLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(userId: Int?, global: Boolean): FeedFragment {
|
||||||
|
val fragment = FeedFragment()
|
||||||
|
val args = Bundle()
|
||||||
|
args.putInt("userId", userId ?: -1)
|
||||||
|
args.putBoolean("global", global)
|
||||||
|
fragment.arguments = args
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,18 +3,23 @@ package ani.dantotsu.profile.activity
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
|
import ani.dantotsu.connections.anilist.AnilistQueries
|
||||||
import ani.dantotsu.connections.anilist.api.Notification
|
import ani.dantotsu.connections.anilist.api.Notification
|
||||||
import ani.dantotsu.databinding.ActivityFollowBinding
|
import ani.dantotsu.databinding.ActivityFollowBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.media.MediaDetailsActivity
|
import ani.dantotsu.media.MediaDetailsActivity
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
import ani.dantotsu.profile.ProfileActivity
|
import ani.dantotsu.profile.ProfileActivity
|
||||||
|
import ani.dantotsu.snackString
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
import com.xwray.groupie.GroupieAdapter
|
import com.xwray.groupie.GroupieAdapter
|
||||||
|
@ -26,8 +31,9 @@ class NotificationActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityFollowBinding
|
private lateinit var binding: ActivityFollowBinding
|
||||||
private var adapter: GroupieAdapter = GroupieAdapter()
|
private var adapter: GroupieAdapter = GroupieAdapter()
|
||||||
private var notificationList: List<Notification> = emptyList()
|
private var notificationList: List<Notification> = emptyList()
|
||||||
|
private var page: Int = 1
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
ThemeManager(this).applyTheme()
|
ThemeManager(this).applyTheme()
|
||||||
|
@ -36,6 +42,7 @@ class NotificationActivity : AppCompatActivity() {
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
binding.listTitle.text = "Notifications"
|
binding.listTitle.text = "Notifications"
|
||||||
binding.listToolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = statusBarHeight }
|
binding.listToolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = statusBarHeight }
|
||||||
|
binding.listFrameLayout.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin = navBarHeight }
|
||||||
binding.listRecyclerView.adapter = adapter
|
binding.listRecyclerView.adapter = adapter
|
||||||
binding.listRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
binding.listRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
binding.followerGrid.visibility = ViewGroup.GONE
|
binding.followerGrid.visibility = ViewGroup.GONE
|
||||||
|
@ -52,6 +59,30 @@ class NotificationActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main){
|
withContext(Dispatchers.Main){
|
||||||
binding.listProgressBar.visibility = ViewGroup.GONE
|
binding.listProgressBar.visibility = ViewGroup.GONE
|
||||||
|
binding.listRecyclerView.setOnTouchListener { _, event ->
|
||||||
|
if (event?.action == MotionEvent.ACTION_UP) {
|
||||||
|
if (adapter.itemCount % AnilistQueries.ITEMS_PER_PAGE != 0) {
|
||||||
|
snackString("No more notifications")
|
||||||
|
} else if (!binding.listRecyclerView.canScrollVertically(1) && !binding.followRefresh.isVisible
|
||||||
|
&& binding.listRecyclerView.adapter!!.itemCount != 0 &&
|
||||||
|
(binding.listRecyclerView.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() == (binding.listRecyclerView.adapter!!.itemCount - 1)
|
||||||
|
) {
|
||||||
|
page++
|
||||||
|
binding.followRefresh.visibility = ViewGroup.VISIBLE
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val res = Anilist.query.getNotifications(Anilist.userid?:0, page)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
res?.data?.page?.notifications?.let { notifications ->
|
||||||
|
notificationList += notifications
|
||||||
|
adapter.addAll(notifications.map { NotificationItem(it, ::onNotificationClick) })
|
||||||
|
}
|
||||||
|
binding.followRefresh.visibility = ViewGroup.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import ani.dantotsu.incognitoNotification
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.profile.activity.NotificationActivity
|
import ani.dantotsu.profile.activity.NotificationActivity
|
||||||
import ani.dantotsu.offline.OfflineFragment
|
import ani.dantotsu.offline.OfflineFragment
|
||||||
|
import ani.dantotsu.profile.activity.FeedActivity
|
||||||
import ani.dantotsu.setSafeOnClickListener
|
import ani.dantotsu.setSafeOnClickListener
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
|
@ -108,6 +109,11 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.settingsActivity.setSafeOnClickListener {
|
||||||
|
startActivity(Intent(activity, FeedActivity::class.java))
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
binding.settingsNotification.setOnClickListener {
|
binding.settingsNotification.setOnClickListener {
|
||||||
startActivity(Intent(activity, NotificationActivity::class.java))
|
startActivity(Intent(activity, NotificationActivity::class.java))
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|
10
app/src/main/res/drawable/ic_globe_24.xml
Normal file
10
app/src/main/res/drawable/ic_globe_24.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M480,880q-82,0 -155,-31.5t-127.5,-86Q143,708 111.5,635T80,480q0,-83 31.5,-155.5t86,-127Q252,143 325,111.5T480,80q83,0 155.5,31.5t127,86q54.5,54.5 86,127T880,480q0,82 -31.5,155t-86,127.5q-54.5,54.5 -127,86T480,880ZM480,798q26,-36 45,-75t31,-83L404,640q12,44 31,83t45,75ZM376,782q-18,-33 -31.5,-68.5T322,640L204,640q29,50 72.5,87t99.5,55ZM584,782q56,-18 99.5,-55t72.5,-87L638,640q-9,38 -22.5,73.5T584,782ZM170,560h136q-3,-20 -4.5,-39.5T300,480q0,-21 1.5,-40.5T306,400L170,400q-5,20 -7.5,39.5T160,480q0,21 2.5,40.5T170,560ZM386,560h188q3,-20 4.5,-39.5T580,480q0,-21 -1.5,-40.5T574,400L386,400q-3,20 -4.5,39.5T380,480q0,21 1.5,40.5T386,560ZM654,560h136q5,-20 7.5,-39.5T800,480q0,-21 -2.5,-40.5T790,400L654,400q3,20 4.5,39.5T660,480q0,21 -1.5,40.5T654,560ZM638,320h118q-29,-50 -72.5,-87T584,178q18,33 31.5,68.5T638,320ZM404,320h152q-12,-44 -31,-83t-45,-75q-26,36 -45,75t-31,83ZM204,320h118q9,-38 22.5,-73.5T376,178q-56,18 -99.5,55T204,320Z"/>
|
||||||
|
</vector>
|
|
@ -1,19 +1,13 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/listProgressBar"
|
|
||||||
style="?android:attr/progressBarStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:id="@+id/listToolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
@ -38,18 +32,38 @@
|
||||||
android:fontFamily="@font/poppins_bold"
|
android:fontFamily="@font/poppins_bold"
|
||||||
android:gravity="center|start"
|
android:gravity="center|start"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="Activity"
|
|
||||||
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
|
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
|
||||||
android:textColor="?attr/colorOnBackground"
|
android:textColor="?attr/colorOnBackground"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
tools:ignore="HardcodedText" />
|
tools:text="Activities" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/listRecyclerView"
|
android:id="@+id/feedViewPager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginBottom="72dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginTop="48dp"
|
||||||
tools:listitem="@layout/item_activity" />
|
tools:ignore="SpeakableTextPresentCheck" />
|
||||||
</LinearLayout>
|
|
||||||
|
<nl.joery.animatedbottombar.AnimatedBottomBar
|
||||||
|
android:id="@+id/feedNavBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="72dp"
|
||||||
|
android:layout_gravity="center_horizontal|bottom"
|
||||||
|
android:background="?attr/colorSurface"
|
||||||
|
android:padding="0dp"
|
||||||
|
app:abb_animationInterpolator="@anim/over_shoot"
|
||||||
|
app:abb_indicatorAppearance="round"
|
||||||
|
app:abb_indicatorLocation="top"
|
||||||
|
app:abb_selectedTabType="text"
|
||||||
|
app:abb_textAppearance="@style/NavBarText"
|
||||||
|
app:itemActiveIndicatorStyle="@style/BottomNavBar"
|
||||||
|
app:itemIconTint="@color/tab_layout_icon"
|
||||||
|
app:itemRippleColor="#00000000"
|
||||||
|
app:itemTextAppearanceActive="@style/NavBarText"
|
||||||
|
app:itemTextAppearanceInactive="@style/NavBarText"
|
||||||
|
app:itemTextColor="@color/tab_layout_icon" />
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -93,11 +93,26 @@
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<FrameLayout
|
||||||
android:id="@+id/listRecyclerView"
|
android:id="@+id/listFrameLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
tools:listitem="@layout/item_follower" />
|
android:id="@+id/listRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:nestedScrollingEnabled="true" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/followRefresh"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|center_horizontal"
|
||||||
|
android:layout_marginBottom="32dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -20,6 +20,7 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/profileScrollView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="72dp"
|
android:layout_marginBottom="72dp"
|
||||||
|
@ -118,15 +119,6 @@
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/profileActivityButton"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:contentDescription="@string/menu"
|
|
||||||
android:src="@drawable/inbox_empty"
|
|
||||||
app:tint="@color/bg_opp" />
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/profileMenuButton"
|
android:id="@+id/profileMenuButton"
|
||||||
android:layout_width="32dp"
|
android:layout_width="32dp"
|
||||||
|
|
|
@ -1,6 +1,42 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<ProgressBar
|
||||||
|
android:id="@+id/listProgressBar"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/listRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:nestedScrollingEnabled="true"
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:listitem="@layout/item_activity" />
|
||||||
|
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/feedRefresh"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|center_horizontal"
|
||||||
|
android:layout_marginBottom="32dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -70,14 +70,14 @@
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/activityFavorite"
|
android:id="@+id/activityLike"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/ic_round_favorite_24"
|
android:src="@drawable/ic_round_favorite_24"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/activityFavoriteCount"
|
android:id="@+id/activityLikeCount"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue