feat: statistics page (wip)
This commit is contained in:
parent
00dad2ad48
commit
42b0a3b62b
6 changed files with 433 additions and 1 deletions
|
@ -127,6 +127,7 @@ dependencies {
|
|||
implementation 'com.github.VipulOG:ebook-reader:0.1.6'
|
||||
implementation 'androidx.paging:paging-runtime-ktx:3.2.1'
|
||||
implementation 'com.github.eltos:simpledialogfragments:v3.7'
|
||||
implementation 'com.github.AAChartModel:AAChartCore-Kotlin:-SNAPSHOT'
|
||||
|
||||
// Markwon
|
||||
ext.markwon_version = '4.6.2'
|
||||
|
|
|
@ -11,6 +11,7 @@ import ani.dantotsu.currContext
|
|||
import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import java.util.Calendar
|
||||
|
@ -124,7 +125,7 @@ object Anilist {
|
|||
show: Boolean = false,
|
||||
cache: Int? = null
|
||||
): T? {
|
||||
return tryWithSuspend {
|
||||
return try {
|
||||
if (rateLimitReset > System.currentTimeMillis() / 1000) {
|
||||
toast("Rate limited. Try after ${rateLimitReset - (System.currentTimeMillis() / 1000)} seconds")
|
||||
throw Exception("Rate limited after ${rateLimitReset - (System.currentTimeMillis() / 1000)} seconds")
|
||||
|
@ -163,6 +164,10 @@ object Anilist {
|
|||
if (show) println("Response : ${json.text}")
|
||||
json.parsed()
|
||||
} else null
|
||||
} catch (e: Exception) {
|
||||
if (show) snackString("Error fetching Anilist data: ${e.message}")
|
||||
Log.e("AnilistQuery", "Error: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,14 @@ class AnilistQueries {
|
|||
)
|
||||
}
|
||||
|
||||
suspend fun getUserStatistics(id: Int, sort: String = "ID"): Query.StatisticsResponse? {
|
||||
return executeQuery<Query.StatisticsResponse>(
|
||||
"""{User(id:$id){id name statistics{anime{...UserStatistics}manga{...UserStatistics}}}}fragment UserStatistics on UserStatistics{count meanScore standardDeviation minutesWatched episodesWatched chaptersRead volumesRead formats(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds format}statuses(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds status}scores(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds score}lengths(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds length}releaseYears(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds releaseYear}startYears(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds startYear}genres(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds genre}tags(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds tag{id name}}countries(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds country}voiceActors(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds voiceActor{id name{first middle last full native alternative userPreferred}}characterIds}staff(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds staff{id name{first middle last full native alternative userPreferred}}}studios(sort:$sort){count meanScore minutesWatched chaptersRead mediaIds studio{id name isAnimationStudio}}}""",
|
||||
force = true,
|
||||
show = true
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun getMedia(id: Int, mal: Boolean = false): Media? {
|
||||
val response = executeQuery<Query.Media>(
|
||||
"""{Media(${if (!mal) "id:" else "idMal:"}$id){id idMal status chapters episodes nextAiringEpisode{episode}type meanScore isAdult isFavourite format bannerImage coverImage{large}title{english romaji userPreferred}mediaListEntry{progress private score(format:POINT_100)status}}}""",
|
||||
|
|
|
@ -292,6 +292,320 @@ class Query {
|
|||
@SerialName("name")
|
||||
val name: String,
|
||||
)
|
||||
|
||||
//----------------------------------------
|
||||
// Statistics
|
||||
|
||||
@Serializable
|
||||
data class StatisticsResponse(
|
||||
@SerialName("data")
|
||||
val data: Data
|
||||
) {
|
||||
@Serializable
|
||||
data class Data(
|
||||
@SerialName("User")
|
||||
val user: StatisticsUser?
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class StatisticsUser(
|
||||
@SerialName("id")
|
||||
val id: Int,
|
||||
@SerialName("name")
|
||||
val name: String,
|
||||
@SerialName("statistics")
|
||||
val statistics: StatisticsTypes
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsTypes(
|
||||
@SerialName("anime")
|
||||
val anime: Statistics,
|
||||
@SerialName("manga")
|
||||
val manga: Statistics
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Statistics(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("standardDeviation")
|
||||
val standardDeviation: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("episodesWatched")
|
||||
val episodesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("volumesRead")
|
||||
val volumesRead: Int,
|
||||
@SerialName("formats")
|
||||
val formats: List<StatisticsFormat>,
|
||||
@SerialName("statuses")
|
||||
val statuses: List<StatisticsStatus>,
|
||||
@SerialName("scores")
|
||||
val scores: List<StatisticsScore>,
|
||||
@SerialName("lengths")
|
||||
val lengths: List<StatisticsLength>,
|
||||
@SerialName("releaseYears")
|
||||
val releaseYears: List<StatisticsReleaseYear>,
|
||||
@SerialName("startYears")
|
||||
val startYears: List<StatisticsStartYear>,
|
||||
@SerialName("genres")
|
||||
val genres: List<StatisticsGenre>,
|
||||
@SerialName("tags")
|
||||
val tags: List<StatisticsTag>,
|
||||
@SerialName("countries")
|
||||
val countries: List<StatisticsCountry>,
|
||||
@SerialName("voiceActors")
|
||||
val voiceActors: List<StatisticsVoiceActor>,
|
||||
@SerialName("staff")
|
||||
val staff: List<StatisticsStaff>,
|
||||
@SerialName("studios")
|
||||
val studios: List<StatisticsStudio>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsFormat(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("format")
|
||||
val format: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsStatus(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("status")
|
||||
val status: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsScore(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("score")
|
||||
val score: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsLength(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("length")
|
||||
val length: String? //can be null for manga
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsReleaseYear(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("releaseYear")
|
||||
val releaseYear: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsStartYear(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("startYear")
|
||||
val startYear: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsGenre(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("genre")
|
||||
val genre: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsTag(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("tag")
|
||||
val tag: Tag
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Tag(
|
||||
@SerialName("id")
|
||||
val id: Int,
|
||||
@SerialName("name")
|
||||
val name: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsCountry(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("country")
|
||||
val country: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsVoiceActor(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("voiceActor")
|
||||
val voiceActor: VoiceActor,
|
||||
@SerialName("characterIds")
|
||||
val characterIds: List<Int>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class VoiceActor(
|
||||
@SerialName("id")
|
||||
val id: Int,
|
||||
@SerialName("name")
|
||||
val name: StaffName
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StaffName(
|
||||
@SerialName("first")
|
||||
val first: String?,
|
||||
@SerialName("middle")
|
||||
val middle: String?,
|
||||
@SerialName("last")
|
||||
val last: String?,
|
||||
@SerialName("full")
|
||||
val full: String?,
|
||||
@SerialName("native")
|
||||
val native: String?,
|
||||
@SerialName("alternative")
|
||||
val alternative: List<String>?,
|
||||
@SerialName("userPreferred")
|
||||
val userPreferred: String?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsStaff(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("staff")
|
||||
val staff: VoiceActor
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatisticsStudio(
|
||||
@SerialName("count")
|
||||
val count: Int,
|
||||
@SerialName("meanScore")
|
||||
val meanScore: Float,
|
||||
@SerialName("minutesWatched")
|
||||
val minutesWatched: Int,
|
||||
@SerialName("chaptersRead")
|
||||
val chaptersRead: Int,
|
||||
@SerialName("mediaIds")
|
||||
val mediaIds: List<Int>,
|
||||
@SerialName("studio")
|
||||
val studio: StatStudio
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StatStudio(
|
||||
@SerialName("id")
|
||||
val id: Int,
|
||||
@SerialName("name")
|
||||
val name: String,
|
||||
@SerialName("isAnimationStudio")
|
||||
val isAnimationStudio: Boolean
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
//data class WhaData(
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package ani.dantotsu.profile
|
||||
|
||||
class StatisticsActivity {
|
||||
}
|
100
app/src/main/res/layout/fragment_statistics.xml
Normal file
100
app/src/main/res/layout/fragment_statistics.xml
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<nl.joery.animatedbottombar.AnimatedBottomBar
|
||||
android:id="@+id/typeTab"
|
||||
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="bottom"
|
||||
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" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/selectedTabText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:text="Anime"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/formatChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/StatusChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/scoreChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/lengthChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/releaseYearChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/startYearChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/genreChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/tagChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/countryChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/voiceActorChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/staffChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
|
||||
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
|
||||
android:id="@+id/studioChartView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
Loading…
Add table
Add a link
Reference in a new issue