diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt index cdc8ffdd..b8333b6a 100644 --- a/app/src/main/java/ani/dantotsu/Functions.kt +++ b/app/src/main/java/ani/dantotsu/Functions.kt @@ -156,7 +156,7 @@ fun initActivity(a: Activity) { navBarHeight = this.getInsets(WindowInsetsCompat.Type.systemBars()).bottom } } - a.hideStatusBar() + WindowInsetsControllerCompat(window, window.decorView).hide(WindowInsetsCompat.Type.statusBars()) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && statusBarHeight == 0 && a.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { window.decorView.rootWindowInsets?.displayCutout?.apply { if (boundingRects.size > 0) { @@ -176,40 +176,47 @@ fun initActivity(a: Activity) { } } -@Suppress("DEPRECATION") fun Activity.hideSystemBars() { - window.decorView.systemUiVisibility = ( - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - or View.SYSTEM_UI_FLAG_FULLSCREEN - or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - ) + WindowInsetsControllerCompat(window, window.decorView).let { controller -> + controller.systemBarsBehavior = + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + controller.hide(WindowInsetsCompat.Type.systemBars()) + } } -@Suppress("DEPRECATION") -fun Activity.hideStatusBar() { - window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) +fun Activity.setNavigationTheme() { + val a = TypedValue() + theme.resolveAttribute(android.R.attr.colorBackground, a, true) + if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && a.isColorType) + || (a.type >= TypedValue.TYPE_FIRST_COLOR_INT && a.type <= TypedValue.TYPE_LAST_COLOR_INT)) { + window.navigationBarColor = a.data + } } open class BottomSheetDialogFragment : BottomSheetDialogFragment() { override fun onStart() { super.onStart() - val window = dialog?.window - val decorView: View = window?.decorView ?: return - decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN - if (this.resources.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) { - val behavior = BottomSheetBehavior.from(requireView().parent as View) - behavior.state = BottomSheetBehavior.STATE_EXPANDED + dialog?.window?.let { window -> + WindowCompat.setDecorFitsSystemWindows(window, false) + val immersiveMode: Boolean = PrefManager.getVal(PrefName.ImmersiveMode) + if (immersiveMode) { + WindowInsetsControllerCompat( + window, window.decorView + ).hide(WindowInsetsCompat.Type.statusBars()) + } + if (this.resources.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) { + val behavior = BottomSheetBehavior.from(requireView().parent as View) + behavior.state = BottomSheetBehavior.STATE_EXPANDED + } + val typedValue = TypedValue() + val theme = requireContext().theme + theme.resolveAttribute( + com.google.android.material.R.attr.colorSurface, + typedValue, + true + ) + window.navigationBarColor = typedValue.data } - val typedValue = TypedValue() - val theme = requireContext().theme - theme.resolveAttribute( - com.google.android.material.R.attr.colorSurface, - typedValue, - true - ) - window.navigationBarColor = typedValue.data } override fun show(manager: FragmentManager, tag: String?) { diff --git a/app/src/main/java/ani/dantotsu/MainActivity.kt b/app/src/main/java/ani/dantotsu/MainActivity.kt index ba47d2fb..fbfe58a6 100644 --- a/app/src/main/java/ani/dantotsu/MainActivity.kt +++ b/app/src/main/java/ani/dantotsu/MainActivity.kt @@ -22,9 +22,6 @@ import androidx.annotation.OptIn import androidx.appcompat.app.AppCompatActivity import androidx.core.animation.doOnEnd import androidx.core.content.ContextCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.doOnAttach import androidx.core.view.updateLayoutParams import androidx.fragment.app.Fragment @@ -146,24 +143,14 @@ class MainActivity : AppCompatActivity() { finish() } doubleBackToExitPressedOnce = true - WindowInsetsControllerCompat(window, window.decorView) - .show(WindowInsetsCompat.Type.navigationBars()) snackString(this@MainActivity.getString(R.string.back_to_exit)).apply { this?.addCallback(object : BaseTransientBottomBar.BaseCallback() { override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { super.onDismissed(transientBottomBar, event) - WindowInsetsControllerCompat(window, window.decorView).let { controller -> - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - controller.hide(WindowInsetsCompat.Type.navigationBars()) - } + doubleBackToExitPressedOnce = false } }) } - Handler(Looper.getMainLooper()).postDelayed( - { doubleBackToExitPressedOnce = false }, - 2000 - ) } val preferences: SourcePreferences = Injekt.get() @@ -369,13 +356,11 @@ class MainActivity : AppCompatActivity() { override fun onResume() { super.onResume() - - WindowCompat.setDecorFitsSystemWindows(window, false) - - WindowInsetsControllerCompat(window, window.decorView).let { controller -> - controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - controller.hide(WindowInsetsCompat.Type.navigationBars()) + initActivity(this) + binding.includedNavbar.navbarContainer.updateLayoutParams { + bottomMargin = navBarHeight } + window.navigationBarColor = getColor(android.R.color.transparent) } //ViewPager diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt index bbc2bb07..b8d6ad19 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -52,7 +52,7 @@ class AnilistQueries { Anilist.episodesWatched = user.statistics?.anime?.episodesWatched Anilist.chapterRead = user.statistics?.manga?.chaptersRead Anilist.adult = user.options?.displayAdultContent ?: false - Anilist.unreadNotificationCount = user.unreadNotificationCount?:0 + Anilist.unreadNotificationCount = user.unreadNotificationCount ?: 0 return true } @@ -281,7 +281,8 @@ class AnilistQueries { } else { if (currContext()?.let { isOnline(it) } == true) { snackString(currContext()?.getString(R.string.error_getting_data)) - } else { } + } else { + } } } val mal = async { @@ -335,7 +336,11 @@ class AnilistQueries { returnArray.addAll(map.values) return returnArray } - val list = PrefManager.getNullableCustomVal("continueAnimeList", listOf(), List::class.java) as List + val list = PrefManager.getNullableCustomVal( + "continueAnimeList", + listOf(), + List::class.java + ) as List if (list.isNotEmpty()) { list.reversed().forEach { if (map.containsKey(it)) returnArray.add(map[it]!!) @@ -351,7 +356,7 @@ class AnilistQueries { return """ MediaListCollection(userId: ${Anilist.userid}, type: $type, status: $status , sort: UPDATED_TIME ) { lists { entries { progress private score(format:POINT_100) status media { id idMal type isAdult status chapters episodes nextAiringEpisode {episode} meanScore isFavourite format bannerImage coverImage{large} title { english romaji userPreferred } } } } } """ } - suspend fun favMedia(anime: Boolean, id: Int? = Anilist.userid ): ArrayList { + suspend fun favMedia(anime: Boolean, id: Int? = Anilist.userid): ArrayList { var hasNextPage = true var page = 0 @@ -375,7 +380,7 @@ class AnilistQueries { return responseArray } - private fun favMediaQuery(anime: Boolean, page: Int, id: Int?= Anilist.userid ): String { + private fun favMediaQuery(anime: Boolean, page: Int, id: Int? = Anilist.userid): String { return """User(id:${id}){id favourites{${if (anime) "anime" else "manga"}(page:$page){pageInfo{hasNextPage}edges{favouriteOrder node{id idMal isAdult mediaListEntry{ progress private score(format:POINT_100) status } chapters isFavourite format episodes nextAiringEpisode{episode}meanScore isFavourite format startDate{year month day} title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}}}""" } @@ -487,7 +492,11 @@ class AnilistQueries { returnMap["current$type"] = returnArray return } - val list = PrefManager.getNullableCustomVal("continueAnimeList", listOf(), List::class.java) as List + val list = PrefManager.getNullableCustomVal( + "continueAnimeList", + listOf(), + List::class.java + ) as List if (list.isNotEmpty()) { list.reversed().forEach { if (subMap.containsKey(it)) returnArray.add(subMap[it]!!) @@ -512,7 +521,11 @@ class AnilistQueries { subMap[m.id] = m } } - val list = PrefManager.getNullableCustomVal("continueAnimeList", listOf(), List::class.java) as List + val list = PrefManager.getNullableCustomVal( + "continueAnimeList", + listOf(), + List::class.java + ) as List if (list.isNotEmpty()) { list.reversed().forEach { if (subMap.containsKey(it)) returnArray.add(subMap[it]!!) @@ -1291,64 +1304,44 @@ Page(page:$page,perPage:50) { ) } - suspend fun userFavMedia(anime: Boolean, id: Int): ArrayList { - var hasNextPage = true - var page = 0 - - suspend fun getNextPage(page: Int): List { - val response = executeQuery("""{${userFavMediaQuery(anime, page, id)}}""") - val favourites = response?.data?.user?.favourites - val apiMediaList = if (anime) favourites?.anime else favourites?.manga - hasNextPage = apiMediaList?.pageInfo?.hasNextPage ?: false - return apiMediaList?.edges?.mapNotNull { - it.node?.let { i -> - Media(i).apply { isFav = true } - } - } ?: return listOf() - } - - val responseArray = arrayListOf() - while (hasNextPage) { - page++ - responseArray.addAll(getNextPage(page)) - } - return responseArray - } - private fun userFavMediaQuery(anime: Boolean, page: Int, id: Int): String { return """User(id:${id}){id favourites{${if (anime) "anime" else "manga"}(page:$page){pageInfo{hasNextPage}edges{favouriteOrder node{id idMal isAdult mediaListEntry{ progress private score(format:POINT_100) status } chapters isFavourite format episodes nextAiringEpisode{episode}meanScore isFavourite format startDate{year month day} title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}}}""" } - suspend fun userFollowing(id: Int): Query.Following?{ - return executeQuery("""{Page {following(userId:${id},sort:[USERNAME]){id name avatar{large medium}bannerImage}}}""", force = true) + suspend fun userFollowing(id: Int): Query.Following? { + return executeQuery( + """{Page {following(userId:${id},sort:[USERNAME]){id name avatar{large medium}bannerImage}}}""", + force = true + ) } - suspend fun userFollowers(id: Int): Query.Follower?{ - return executeQuery("""{Page {followers(userId:${id},sort:[USERNAME]){id name avatar{large medium}bannerImage}}}""", force = true) + suspend fun userFollowers(id: Int): Query.Follower? { + return executeQuery( + """{Page {followers(userId:${id},sort:[USERNAME]){id name avatar{large medium}bannerImage}}}""", + force = true + ) } - private suspend fun userBannerImage(type: String,id: Int?): String? { - val response = - executeQuery("""{ MediaListCollection(userId: ${id}, type: $type, chunk:1,perChunk:25, sort: [SCORE_DESC,UPDATED_TIME_DESC]) { lists { entries{ media { id bannerImage } } } } } """) - val random = response?.data?.mediaListCollection?.lists?.mapNotNull { - it.entries?.mapNotNull { entry -> - val imageUrl = entry.media?.bannerImage - if (imageUrl != null && imageUrl != "null") imageUrl - else null - } - }?.flatten()?.randomOrNull() ?: return null - return random + suspend fun initProfilePage(id: Int): Query.ProfilePageMedia? { + return executeQuery( + """{ + favoriteAnime:${userFavMediaQuery(true, 1, id)} + favoriteManga:${userFavMediaQuery(false, 1, id)} + animeMediaList:${bannerImageQuery("ANIME", id)} + mangaMediaList:${bannerImageQuery("MANGA", id)} + }""".trimIndent(), force = true + ) } - suspend fun getUserBannerImages(id: Int? = Anilist.userid): ArrayList { - val default = arrayListOf(null, null) - default[0] = userBannerImage("ANIME", id) - default[1] = userBannerImage("MANGA",id) - return default + private fun bannerImageQuery(type: String, id: Int?): String { + return """MediaListCollection(userId: ${id}, type: $type, chunk:1,perChunk:25, sort: [SCORE_DESC,UPDATED_TIME_DESC]) { lists { entries{ media { id bannerImage } } } }""" } suspend fun getNotifications(id: Int, page: Int = 1): NotificationResponse? { - val res = executeQuery("""{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) + val res = executeQuery( + """{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) { Anilist.unreadNotificationCount = 0 } @@ -1359,7 +1352,9 @@ Page(page:$page,perPage:50) { val filter = if (userId != null) "userId:$userId," else if (global) "isFollowing:false," else "isFollowing:true," - val res = executeQuery("""{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}}}}}}""") + val res = executeQuery( + """{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 } diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt index f9535263..07d93b9c 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -7,10 +7,8 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import ani.dantotsu.BuildConfig import ani.dantotsu.R -import ani.dantotsu.connections.comments.CommentsAPI import ani.dantotsu.connections.discord.Discord import ani.dantotsu.connections.mal.MAL -import ani.dantotsu.media.Character import ani.dantotsu.media.Media import ani.dantotsu.others.AppUpdater import ani.dantotsu.settings.saving.PrefManager @@ -335,24 +333,57 @@ class GenresViewModel : ViewModel() { } } -class ProfileViewModel : ViewModel(){ +class ProfileViewModel : ViewModel() { private val mangaFav: MutableLiveData> = MutableLiveData>(null) + fun getMangaFav(): LiveData> = mangaFav private val animeFav: MutableLiveData> = MutableLiveData>(null) + fun getAnimeFav(): LiveData> = animeFav private val listImages: MutableLiveData> = MutableLiveData>(arrayListOf()) + fun getListImages(): LiveData> = listImages suspend fun setData(id: Int) { - mangaFav.postValue(Anilist.query.userFavMedia(false, id)) - animeFav.postValue(Anilist.query.userFavMedia(true, id)) - listImages.postValue(Anilist.query.getUserBannerImages(id)) + val res = Anilist.query.initProfilePage(id) + val mangaList = res?.data?.favoriteManga?.favourites?.manga?.edges?.mapNotNull { + it.node?.let { i -> + Media(i).apply { isFav = true } + } + } + mangaFav.postValue(ArrayList(mangaList ?: arrayListOf())) + val animeList = res?.data?.favoriteAnime?.favourites?.anime?.edges?.mapNotNull { + it.node?.let { i -> + Media(i).apply { isFav = true } + } + } + animeFav.postValue(ArrayList(animeList ?: arrayListOf())) + + val bannerImages = arrayListOf(null, null) + val animeRandom = res?.data?.animeMediaList?.lists?.mapNotNull { + it.entries?.mapNotNull { entry -> + val imageUrl = entry.media?.bannerImage + if (imageUrl != null && imageUrl != "null") imageUrl + else null + } + }?.flatten()?.randomOrNull() + bannerImages[0] = animeRandom + val mangaRandom = res?.data?.mangaMediaList?.lists?.mapNotNull { + it.entries?.mapNotNull { entry -> + val imageUrl = entry.media?.bannerImage + if (imageUrl != null && imageUrl != "null") imageUrl + else null + } + }?.flatten()?.randomOrNull() + bannerImages[1] = mangaRandom + listImages.postValue(bannerImages) + } fun refresh() { diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt index fc074559..bf4310a7 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Data.kt @@ -139,6 +139,20 @@ class Query { ) } + @Serializable + data class ProfilePageMedia( + @SerialName("data") + val data: Data? + ) { + @Serializable + data class Data( + @SerialName("favoriteAnime") val favoriteAnime: ani.dantotsu.connections.anilist.api.User?, + @SerialName("favoriteManga") val favoriteManga: ani.dantotsu.connections.anilist.api.User?, + @SerialName("animeMediaList") val animeMediaList: ani.dantotsu.connections.anilist.api.MediaListCollection?, + @SerialName("mangaMediaList") val mangaMediaList: ani.dantotsu.connections.anilist.api.MediaListCollection? + ) + } + @Serializable data class ToggleFollow( @SerialName("data") diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Feed.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Feed.kt index b8cc5cc9..8b6e2814 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Feed.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Feed.kt @@ -63,6 +63,10 @@ data class Activity( val createdAt: Int, @SerialName("user") val user: User?, + @SerialName("recipient") + val recipient: User?, + @SerialName("messenger") + val messenger: User?, @SerialName("media") val media: Media?, @SerialName("replies") diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt index 646b1744..25af1d1d 100644 --- a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt @@ -5,13 +5,12 @@ import android.annotation.SuppressLint import android.app.AlertDialog import android.content.Context.INPUT_METHOD_SERVICE import android.graphics.drawable.ColorDrawable -import android.graphics.drawable.Drawable import android.os.Bundle import android.text.TextWatcher import android.view.LayoutInflater +import android.view.MotionEvent import android.view.View import android.view.ViewGroup -import android.view.WindowManager import android.view.inputmethod.InputMethodManager import android.widget.EditText import androidx.appcompat.app.AppCompatActivity @@ -27,36 +26,15 @@ import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.comments.Comment import ani.dantotsu.connections.comments.CommentResponse import ani.dantotsu.connections.comments.CommentsAPI -import ani.dantotsu.copyToClipboard import ani.dantotsu.databinding.FragmentCommentsBinding import ani.dantotsu.loadImage -import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString -import com.bumptech.glide.Glide -import com.bumptech.glide.RequestBuilder -import com.bumptech.glide.RequestManager -import com.bumptech.glide.load.DataSource -import com.bumptech.glide.load.engine.GlideException -import com.bumptech.glide.load.resource.gif.GifDrawable -import com.bumptech.glide.request.RequestListener -import com.bumptech.glide.request.target.Target import com.xwray.groupie.GroupieAdapter import com.xwray.groupie.Section -import io.noties.markwon.AbstractMarkwonPlugin -import io.noties.markwon.Markwon -import io.noties.markwon.MarkwonConfiguration -import io.noties.markwon.SoftBreakAddsNewLinePlugin import io.noties.markwon.editor.MarkwonEditor import io.noties.markwon.editor.MarkwonEditorTextWatcher -import io.noties.markwon.ext.strikethrough.StrikethroughPlugin -import io.noties.markwon.ext.tables.TablePlugin -import io.noties.markwon.ext.tasklist.TaskListPlugin -import io.noties.markwon.html.HtmlPlugin -import io.noties.markwon.html.TagHandlerNoOp -import io.noties.markwon.image.AsyncDrawable -import io.noties.markwon.image.glide.GlideImagesPlugin import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -64,6 +42,7 @@ import java.text.SimpleDateFormat import java.util.Locale import java.util.TimeZone +@SuppressLint("ClickableViewAccessibility") class CommentsFragment : Fragment() { lateinit var binding: FragmentCommentsBinding lateinit var activity: AppCompatActivity @@ -193,8 +172,68 @@ class CommentsFragment : Fragment() { } var isFetching = false + binding.commentsList.setOnTouchListener( + object : View.OnTouchListener { + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + if (event?.action == MotionEvent.ACTION_UP) { + if (!binding.commentsList.canScrollVertically(1) && !isFetching && + (binding.commentsList.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() == (binding.commentsList.adapter!!.itemCount - 1) + ) { + if (pagesLoaded < totalPages) { + binding.commentBottomRefresh.visibility = View.VISIBLE + loadMoreComments() + lifecycleScope.launch { + kotlinx.coroutines.delay(1000) + withContext(Dispatchers.Main) { + binding.commentBottomRefresh.visibility = View.GONE + } + } + } else { + snackString("No more comments") + } + } + } + return false + } + + private fun loadMoreComments() { + isFetching = true + lifecycleScope.launch { + val comments = fetchComments() + comments?.comments?.forEach { comment -> + updateUIWithComment(comment) + } + totalPages = comments?.totalPages ?: 1 + pagesLoaded++ + isFetching = false + } + } + + private suspend fun fetchComments(): CommentResponse? { + return withContext(Dispatchers.IO) { + CommentsAPI.getCommentsForId(mediaId, pagesLoaded + 1, filterTag) + } + } + + //adds additional comments to the section + private suspend fun updateUIWithComment(comment: Comment) { + withContext(Dispatchers.Main) { + section.add( + CommentItem( + comment, + buildMarkwon(activity), + section, + this@CommentsFragment, + backgroundColor, + 0 + ) + ) + } + } + }) + //if we have scrolled to the bottom of the list, load more comments - binding.commentsList.addOnScrollListener(object : + /*binding.commentsList.addOnScrollListener(object : androidx.recyclerview.widget.RecyclerView.OnScrollListener() { override fun onScrolled( recyclerView: androidx.recyclerview.widget.RecyclerView, @@ -245,7 +284,7 @@ class CommentsFragment : Fragment() { ) } } - }) + })*/ binding.commentInput.addTextChangedListener(object : TextWatcher { diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt index 2d570043..6b979319 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt @@ -601,6 +601,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { super.onResume() binding.mediaInfoProgressBar.visibility = progress binding.animeSourceRecycler.layoutManager?.onRestoreInstanceState(state) + requireActivity().setNavigationTheme() } override fun onPause() { diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt index a6ce9bd3..3665eb3e 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt @@ -285,7 +285,7 @@ class MangaReaderActivity : AppCompatActivity() { binding.mangaReaderNextChapter.performClick() } binding.mangaReaderNextChapter.setOnClickListener { - if (defaultSettings.direction == RIGHT_TO_LEFT) { + if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { if (currentChapterIndex > 0) change(currentChapterIndex - 1) else snackString(getString(R.string.first_chapter)) } else { @@ -298,7 +298,7 @@ class MangaReaderActivity : AppCompatActivity() { binding.mangaReaderPreviousChapter.performClick() } binding.mangaReaderPreviousChapter.setOnClickListener { - if (defaultSettings.direction == RIGHT_TO_LEFT) { + if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { if (chaptersArr.size > currentChapterIndex + 1) progress { change(currentChapterIndex + 1) } else snackString(getString(R.string.next_chapter_not_found)) } else { @@ -315,7 +315,7 @@ class MangaReaderActivity : AppCompatActivity() { PrefManager.setCustomVal("${media.id}_current_chp", chap.number) currentChapterIndex = chaptersArr.indexOf(chap.number) binding.mangaReaderChapterSelect.setSelection(currentChapterIndex) - if (defaultSettings.direction == RIGHT_TO_LEFT) { + if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { binding.mangaReaderNextChap.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: "" binding.mangaReaderPrevChap.text = @@ -439,6 +439,10 @@ class MangaReaderActivity : AppCompatActivity() { if ((defaultSettings.direction == TOP_TO_BOTTOM || defaultSettings.direction == BOTTOM_TO_TOP)) { binding.mangaReaderSwipy.vertical = true if (defaultSettings.direction == TOP_TO_BOTTOM) { + binding.mangaReaderNextChap.text = + chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: "" + binding.mangaReaderPrevChap.text = + chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: "" binding.BottomSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: getString(R.string.no_chapter) binding.TopSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) @@ -450,6 +454,10 @@ class MangaReaderActivity : AppCompatActivity() { binding.mangaReaderNextChapter.performClick() } } else { + binding.mangaReaderNextChap.text = + chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: "" + binding.mangaReaderPrevChap.text = + chaptersTitleArr.getOrNull(currentChapterIndex + 1) ?: "" binding.BottomSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex - 1) ?: getString(R.string.no_chapter) binding.TopSwipeText.text = chaptersTitleArr.getOrNull(currentChapterIndex + 1) @@ -729,7 +737,7 @@ class MangaReaderActivity : AppCompatActivity() { val screenWidth = Resources.getSystem().displayMetrics.widthPixels //if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left if (screenWidth / 5 in x + 1.. screenWidth - screenWidth / 5 && y > screenWidth / 5) { - pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT) { + pressLocation = if (defaultSettings.direction == RIGHT_TO_LEFT || defaultSettings.direction == BOTTOM_TO_TOP) { pressPos.LEFT } else { pressPos.RIGHT diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt b/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt index a7f8216d..ac3c64a9 100644 --- a/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt +++ b/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt @@ -1,8 +1,10 @@ package ani.dantotsu.profile +import android.animation.ObjectAnimator import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle +import android.util.TypedValue import android.view.View import android.view.ViewGroup import android.widget.PopupMenu @@ -29,13 +31,15 @@ import ani.dantotsu.snackString import ani.dantotsu.statusBarHeight import ani.dantotsu.themes.ThemeManager import ani.dantotsu.toast +import com.google.android.material.appbar.AppBarLayout import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import nl.joery.animatedbottombar.AnimatedBottomBar +import kotlin.math.abs -class ProfileActivity : AppCompatActivity() { +class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListener { lateinit var binding: ActivityProfileBinding private var selected: Int = 1 private lateinit var navBar: AnimatedBottomBar @@ -47,6 +51,7 @@ class ProfileActivity : AppCompatActivity() { initActivity(this) binding = ActivityProfileBinding.inflate(layoutInflater) setContentView(binding.root) + screenWidth = resources.displayMetrics.widthPixels.toFloat() navBar = binding.profileNavBar navBar.updateLayoutParams { bottomMargin = navBarHeight } val feedTab = navBar.createTab(R.drawable.ic_round_filter_24, "Feed") @@ -57,6 +62,7 @@ class ProfileActivity : AppCompatActivity() { navBar.addTab(statsTab) navBar.visibility = View.GONE binding.profileViewPager.isUserInputEnabled = false + lifecycleScope.launch(Dispatchers.IO) { val userid = intent.getIntExtra("userId", 0) val respond = Anilist.query.getUserProfile(userid) @@ -72,6 +78,7 @@ class ProfileActivity : AppCompatActivity() { } binding.profileViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, user) + binding.profileViewPager.setOffscreenPageLimit(3) binding.profileViewPager.setCurrentItem(selected, false) navBar.visibility = View.VISIBLE navBar.selectTabAt(selected) @@ -163,10 +170,50 @@ class ProfileActivity : AppCompatActivity() { ) } + mMaxScrollSize = binding.profileAppBar.totalScrollRange + binding.profileAppBar.addOnOffsetChangedListener(this@ProfileActivity) } } } + //Collapsing UI Stuff + private var isCollapsed = false + private val percent = 45 + private var mMaxScrollSize = 0 + private var screenWidth: Float = 0f + + override fun onOffsetChanged(appBar: AppBarLayout, i: Int) { + if (mMaxScrollSize == 0) mMaxScrollSize = appBar.totalScrollRange + val percentage = abs(i) * 100 / mMaxScrollSize + + binding.profileUserAvatarContainer.visibility = + if (binding.profileUserAvatarContainer.scaleX == 0f) View.GONE else View.VISIBLE + val duration = (200 * (PrefManager.getVal(PrefName.AnimationSpeed) as Float)).toLong() + val typedValue = TypedValue() + this@ProfileActivity.theme.resolveAttribute( + com.google.android.material.R.attr.colorSecondary, + typedValue, + true + ) + val color = typedValue.data + if (percentage >= percent && !isCollapsed) { + isCollapsed = true + ObjectAnimator.ofFloat(binding.profileUserDataContainer, "translationX", screenWidth) + .setDuration(duration).start() + ObjectAnimator.ofFloat(binding.profileUserAvatarContainer, "translationX", screenWidth) + .setDuration(duration).start() + binding.profileBannerImage.pause() + } + if (percentage <= percent && isCollapsed) { + isCollapsed = false + ObjectAnimator.ofFloat(binding.profileUserDataContainer, "translationX", 0f) + .setDuration(duration).start() + ObjectAnimator.ofFloat(binding.profileUserAvatarContainer, "translationX", 0f).setDuration(duration) + .start() + if (PrefManager.getVal(PrefName.BannerAnimations)) binding.profileBannerImage.resume() + } + } + override fun onResume() { if (this::navBar.isInitialized) { navBar.selectTabAt(selected) diff --git a/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt b/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt index bb245f47..1fdeef98 100644 --- a/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter +import androidx.core.view.updateLayoutParams import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager @@ -16,6 +17,7 @@ import ani.dantotsu.profile.ChartBuilder.Companion.ChartPacket import ani.dantotsu.profile.ChartBuilder.Companion.ChartType import ani.dantotsu.profile.ChartBuilder.Companion.MediaType import ani.dantotsu.profile.ChartBuilder.Companion.StatType +import ani.dantotsu.statusBarHeight import com.github.aachartmodel.aainfographics.aachartcreator.AAChartType import com.xwray.groupie.GroupieAdapter import kotlinx.coroutines.Dispatchers @@ -32,6 +34,7 @@ class StatsFragment : private var statType: StatType = StatType.COUNT private lateinit var user: Query.UserProfile private lateinit var activity: ProfileActivity + private var loadedFirstTime = false override fun onCreateView( inflater: LayoutInflater, @@ -49,10 +52,11 @@ class StatsFragment : binding.statisticList.adapter = adapter binding.statisticList.setHasFixedSize(true) - binding.statisticList.isNestedScrollingEnabled = false + binding.statisticList.isNestedScrollingEnabled = true binding.statisticList.layoutManager = LinearLayoutManager(requireContext()) binding.statisticProgressBar.visibility = View.VISIBLE binding.compare.visibility = if (user.id == Anilist.userid) View.GONE else View.VISIBLE + binding.filterContainer.updateLayoutParams { topMargin = statusBarHeight } binding.sourceType.setAdapter( ArrayAdapter( @@ -98,29 +102,32 @@ class StatsFragment : } binding.filterContainer.visibility = View.GONE - activity.lifecycleScope.launch { - stats.clear() - stats.add(Anilist.query.getUserStatistics(user.id)?.data?.user) - withContext(Dispatchers.Main) { - binding.filterContainer.visibility = View.VISIBLE - binding.sourceType.setOnItemClickListener { _, _, i, _ -> - type = MediaType.entries.toTypedArray()[i] - loadStats(type == MediaType.ANIME) - } - binding.sourceFilter.setOnItemClickListener { _, _, i, _ -> - statType = StatType.entries.toTypedArray()[i] - loadStats(type == MediaType.ANIME) - } - loadStats(type == MediaType.ANIME) - binding.statisticProgressBar.visibility = View.GONE - } - } } override fun onResume() { super.onResume() if (this::binding.isInitialized) { binding.root.requestLayout() + if (!loadedFirstTime) { + activity.lifecycleScope.launch { + stats.clear() + stats.add(Anilist.query.getUserStatistics(user.id)?.data?.user) + withContext(Dispatchers.Main) { + binding.filterContainer.visibility = View.VISIBLE + binding.sourceType.setOnItemClickListener { _, _, i, _ -> + type = MediaType.entries.toTypedArray()[i] + loadStats(type == MediaType.ANIME) + } + binding.sourceFilter.setOnItemClickListener { _, _, i, _ -> + statType = StatType.entries.toTypedArray()[i] + loadStats(type == MediaType.ANIME) + } + loadStats(type == MediaType.ANIME) + binding.statisticProgressBar.visibility = View.GONE + } + } + loadedFirstTime = true + } } loadStats(type == MediaType.ANIME) } diff --git a/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt b/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt index c69d5950..1a112de5 100644 --- a/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt +++ b/app/src/main/java/ani/dantotsu/profile/activity/ActivityItem.kt @@ -33,15 +33,15 @@ class ActivityItem( override fun bind(viewBinding: ItemActivityBinding, position: Int) { binding = viewBinding - binding.activityUserName.text = activity.user?.name - binding.activityUserAvatar.loadImage(activity.user?.avatar?.medium) + binding.activityUserName.text = activity.user?.name ?: activity.messenger?.name + binding.activityUserAvatar.loadImage(activity.user?.avatar?.medium ?: activity.messenger?.avatar?.medium) binding.activityTime.text = ActivityItemBuilder.getDateTime(activity.createdAt) val likeColor = ContextCompat.getColor(binding.root.context, R.color.yt_red) val notLikeColor = ContextCompat.getColor(binding.root.context, R.color.bg_opp) binding.activityLike.setColorFilter(if (activity.isLiked == true) likeColor else notLikeColor) binding.commentRepliesContainer.visibility = if (activity.replyCount > 0) View.VISIBLE else View.GONE - binding.activityLikeCount.text = activity.likeCount.toString() + binding.activityLikeCount.text = (activity.likeCount?:0).toString() binding.activityLike.setOnClickListener { val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) @@ -55,7 +55,7 @@ class ActivityItem( } else { activity.likeCount = activity.likeCount?.plus(1) } - binding.activityLikeCount.text = activity.likeCount.toString() + binding.activityLikeCount.text = (activity.likeCount?:0).toString() activity.isLiked = !activity.isLiked!! binding.activityLike.setColorFilter(if (activity.isLiked == true) likeColor else notLikeColor) @@ -99,6 +99,15 @@ class ActivityItem( markwon.setMarkdown(binding.activityContent, activity.text ?: "") } } + + "MessageActivity" -> { + binding.activityBannerContainer.visibility = View.GONE + binding.activityContent.visibility = View.VISIBLE + if (!(context as android.app.Activity).isDestroyed) { + val markwon = buildMarkwon(context, false) + markwon.setMarkdown(binding.activityContent, activity.message ?: "") + } + } } } diff --git a/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt b/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt index f6751d53..353748d7 100644 --- a/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt @@ -28,6 +28,9 @@ class FeedFragment : Fragment() { private var activityList: List = emptyList() private lateinit var activity: androidx.activity.ComponentActivity private var page: Int = 1 + private var loadedFirstTime = false + private var userId: Int? = null + private var global: Boolean = false override fun onCreateView( inflater: LayoutInflater, @@ -38,7 +41,6 @@ class FeedFragment : Fragment() { return binding.root } - @SuppressLint("ClickableViewAccessibility") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) activity = requireActivity() @@ -46,55 +48,55 @@ class FeedFragment : Fragment() { binding.listRecyclerView.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) binding.listProgressBar.visibility = ViewGroup.VISIBLE - var userId: Int? = arguments?.getInt("userId", -1) + userId = 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 - } - } - } + global = arguments?.getBoolean("global", false) ?: false } + @SuppressLint("ClickableViewAccessibility") override fun onResume() { super.onResume() if (this::binding.isInitialized) { binding.root.requestLayout() + if (!loadedFirstTime) { + 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 = binding.listRecyclerView + + binding.listRecyclerView.setOnTouchListener { _, event -> + if (event?.action == MotionEvent.ACTION_UP) { + if (adapter.itemCount % AnilistQueries.ITEMS_PER_PAGE != 0 && !global) { + 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 + } + } + } + loadedFirstTime = true + } } } diff --git a/app/src/main/java/ani/dantotsu/settings/DevelopersDialogFragment.kt b/app/src/main/java/ani/dantotsu/settings/DevelopersDialogFragment.kt index b7a12ad1..564c0aaa 100644 --- a/app/src/main/java/ani/dantotsu/settings/DevelopersDialogFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/DevelopersDialogFragment.kt @@ -25,6 +25,12 @@ class DevelopersDialogFragment : BottomSheetDialogFragment() { "Contributor", "https://github.com/aayush2622" ), + Developer( + "AbandonedCart", + "https://avatars.githubusercontent.com/u/1173913?v=4", + "Contributor", + "https://github.com/AbandonedCart" + ), Developer( "Sadwhy", "https://avatars.githubusercontent.com/u/99601717?v=4", diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml index 409e6860..5cfbe177 100644 --- a/app/src/main/res/layout/activity_profile.xml +++ b/app/src/main/res/layout/activity_profile.xml @@ -19,17 +19,18 @@ android:layout_height="wrap_content" /> - + android:translationZ="5dp"> - + android:layout_height="wrap_content" + android:fitsSystemWindows="false" + app:contentScrim="?android:colorBackground" + app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> - + - + - + + + + - + android:layout_height="wrap_content" + android:gravity="end" + android:orientation="horizontal" + tools:ignore="UseCompoundDrawables"> - + + + + + + + + + + android:nestedScrollingEnabled="true" + android:visibility="gone" + tools:listitem="@layout/item_comments" + tools:visibility="visible" /> - - - - - - - - - - - - - - - + + @@ -133,8 +132,8 @@ android:id="@+id/commentInputLayout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" android:background="?android:colorBackground" + android:orientation="horizontal" android:paddingTop="8dp" android:paddingBottom="8dp"> @@ -172,18 +171,18 @@ android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="center" - android:background="@drawable/ic_label_off_24" android:layout_marginEnd="8dp" + android:background="@drawable/ic_label_off_24" android:visibility="gone" - tools:visibility="visible" - tools:ignore="ContentDescription" /> + tools:ignore="ContentDescription" + tools:visibility="visible" /> - + @@ -344,9 +349,9 @@ android:layout_marginTop="8dp" android:layout_marginEnd="32dp" android:fontFamily="@font/poppins_bold" - android:text="@string/about_me" android:padding="8dp" - android:textSize="18sp"/> + android:text="@string/about_me" + android:textSize="18sp" /> @@ -464,8 +470,8 @@ android:layout_marginTop="8dp" android:layout_marginEnd="32dp" android:fontFamily="@font/poppins_bold" - android:text="@string/fav_character" android:padding="8dp" + android:text="@string/fav_character" android:textSize="18sp" /> - \ No newline at end of file + + diff --git a/app/src/main/res/layout/fragment_statistics.xml b/app/src/main/res/layout/fragment_statistics.xml index 19aaff14..9f202f6d 100644 --- a/app/src/main/res/layout/fragment_statistics.xml +++ b/app/src/main/res/layout/fragment_statistics.xml @@ -14,7 +14,9 @@ android:layout_height="wrap_content" android:baselineAligned="false" android:orientation="vertical" - android:padding="16dp"> + android:paddingBottom="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp"> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index e1d6f959..87eb6f03 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,6 +1,7 @@