Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
8a1097cd35
15 changed files with 261 additions and 95 deletions
|
@ -784,7 +784,9 @@ fun copyToClipboard(string: String, toast: Boolean = true) {
|
||||||
val clipboard = getSystemService(activity, ClipboardManager::class.java)
|
val clipboard = getSystemService(activity, ClipboardManager::class.java)
|
||||||
val clip = ClipData.newPlainText("label", string)
|
val clip = ClipData.newPlainText("label", string)
|
||||||
clipboard?.setPrimaryClip(clip)
|
clipboard?.setPrimaryClip(clip)
|
||||||
if (toast) snackString(activity.getString(R.string.copied_text, string))
|
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
|
||||||
|
if (toast) snackString(activity.getString(R.string.copied_text, string))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
|
@ -1108,7 +1110,7 @@ fun buildMarkwon(activity: Activity, userInputContent: Boolean = true): Markwon
|
||||||
val markwon = Markwon.builder(activity)
|
val markwon = Markwon.builder(activity)
|
||||||
.usePlugin(object : AbstractMarkwonPlugin() {
|
.usePlugin(object : AbstractMarkwonPlugin() {
|
||||||
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
||||||
builder.linkResolver { view, link ->
|
builder.linkResolver { _, link ->
|
||||||
copyToClipboard(link, true)
|
copyToClipboard(link, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1119,7 +1121,7 @@ fun buildMarkwon(activity: Activity, userInputContent: Boolean = true): Markwon
|
||||||
.usePlugin(TablePlugin.create(activity))
|
.usePlugin(TablePlugin.create(activity))
|
||||||
.usePlugin(TaskListPlugin.create(activity))
|
.usePlugin(TaskListPlugin.create(activity))
|
||||||
.usePlugin(HtmlPlugin.create { plugin ->
|
.usePlugin(HtmlPlugin.create { plugin ->
|
||||||
if (!userInputContent) {
|
if (userInputContent) {
|
||||||
plugin.addHandler(
|
plugin.addHandler(
|
||||||
TagHandlerNoOp.create("h1", "h2", "h3", "h4", "h5", "h6", "hr", "pre", "a")
|
TagHandlerNoOp.create("h1", "h2", "h3", "h4", "h5", "h6", "hr", "pre", "a")
|
||||||
)
|
)
|
||||||
|
|
|
@ -61,14 +61,14 @@ class AnilistQueries {
|
||||||
|
|
||||||
suspend fun getUserProfile(id: Int): Query.UserProfileResponse? {
|
suspend fun getUserProfile(id: Int): Query.UserProfileResponse? {
|
||||||
return executeQuery<Query.UserProfileResponse>(
|
return executeQuery<Query.UserProfileResponse>(
|
||||||
"""{user:User(id:$id){id,name,about(asHtml:true)avatar{medium,large},bannerImage,isFollowing,isFollower,isBlocked,favourites{anime{nodes{coverImage{extraLarge,large,medium,color}}}manga{nodes{id,coverImage{extraLarge,large,medium,color}}}characters{nodes{id,image{large,medium}}}staff{nodes{id,image{large,medium}}}studios{nodes{id,name}}}statistics{anime{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}manga{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}}siteUrl}}""",
|
"""{user:User(id:$id){id,name,about(asHtml:true)avatar{medium,large},bannerImage,isFollowing,isFollower,isBlocked,favourites{anime{nodes{id,coverImage{extraLarge,large,medium,color}}}manga{nodes{id,coverImage{extraLarge,large,medium,color}}}characters{nodes{id,image{large,medium}}}staff{nodes{id,image{large,medium}}}studios{nodes{id,name}}}statistics{anime{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}manga{count,meanScore,standardDeviation,minutesWatched,episodesWatched,chaptersRead,volumesRead}}siteUrl}}""",
|
||||||
force = true
|
force = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getUserStatistics(id: Int, sort: String = "ID"): Query.StatisticsResponse? {
|
suspend fun getUserStatistics(id: Int, sort: String = "ID"): Query.StatisticsResponse? {
|
||||||
return executeQuery<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}}}""",
|
"""{User(id:$id){id name mediaListOptions{scoreFormat}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,
|
force = true,
|
||||||
show = true
|
show = true
|
||||||
)
|
)
|
||||||
|
@ -352,10 +352,10 @@ class AnilistQueries {
|
||||||
returnArray.addAll(map.values)
|
returnArray.addAll(map.values)
|
||||||
return returnArray
|
return returnArray
|
||||||
}
|
}
|
||||||
val set = PrefManager.getVal<Set<String>>(PrefName.ContinuedAnimeSet).toMutableSet()
|
val list = PrefManager.getNullableCustomVal("continueAnimeList", listOf<Int>(), List::class.java) as List<Int>
|
||||||
if (set.isNotEmpty()) {
|
if (list.isNotEmpty()) {
|
||||||
set.forEach {
|
list.reversed().forEach {
|
||||||
if (map.containsKey(it.toInt())) returnArray.add(map[it.toInt()]!!)
|
if (map.containsKey(it)) returnArray.add(map[it]!!)
|
||||||
}
|
}
|
||||||
for (i in map) {
|
for (i in map) {
|
||||||
if (i.value !in returnArray) returnArray.add(i.value)
|
if (i.value !in returnArray) returnArray.add(i.value)
|
||||||
|
@ -504,10 +504,10 @@ class AnilistQueries {
|
||||||
returnMap["current$type"] = returnArray
|
returnMap["current$type"] = returnArray
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val set = PrefManager.getVal<Set<String>>(PrefName.ContinuedAnimeSet).toMutableSet()
|
val list = PrefManager.getNullableCustomVal("continueAnimeList", listOf<Int>(), List::class.java) as List<Int>
|
||||||
if (set.isNotEmpty()) {
|
if (list.isNotEmpty()) {
|
||||||
set.forEach {
|
list.reversed().forEach {
|
||||||
if (subMap.containsKey(it.toInt())) returnArray.add(subMap[it.toInt()]!!)
|
if (subMap.containsKey(it)) returnArray.add(subMap[it]!!)
|
||||||
}
|
}
|
||||||
for (i in subMap) {
|
for (i in subMap) {
|
||||||
if (i.value !in returnArray) returnArray.add(i.value)
|
if (i.value !in returnArray) returnArray.add(i.value)
|
||||||
|
@ -529,9 +529,9 @@ class AnilistQueries {
|
||||||
subMap[m.id] = m
|
subMap[m.id] = m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val set = PrefManager.getCustomVal<Set<Int>>("continue_$type", setOf()).toMutableSet()
|
val list = PrefManager.getNullableCustomVal("continueAnimeList", listOf<Int>(), List::class.java) as List<Int>
|
||||||
if (set.isNotEmpty()) {
|
if (list.isNotEmpty()) {
|
||||||
set.reversed().forEach {
|
list.reversed().forEach {
|
||||||
if (subMap.containsKey(it)) returnArray.add(subMap[it]!!)
|
if (subMap.containsKey(it)) returnArray.add(subMap[it]!!)
|
||||||
}
|
}
|
||||||
for (i in subMap) {
|
for (i in subMap) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ data class Character(
|
||||||
|
|
||||||
// Notes for site moderators
|
// Notes for site moderators
|
||||||
@SerialName("modNotes") var modNotes: String?,
|
@SerialName("modNotes") var modNotes: String?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class CharacterConnection(
|
data class CharacterConnection(
|
||||||
|
@ -56,7 +56,7 @@ data class CharacterConnection(
|
||||||
|
|
||||||
// The pagination information
|
// The pagination information
|
||||||
// @SerialName("pageInfo") var pageInfo: PageInfo?,
|
// @SerialName("pageInfo") var pageInfo: PageInfo?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class CharacterEdge(
|
data class CharacterEdge(
|
||||||
|
@ -82,7 +82,7 @@ data class CharacterEdge(
|
||||||
|
|
||||||
// The order the character should be displayed from the users favourites
|
// The order the character should be displayed from the users favourites
|
||||||
@SerialName("favouriteOrder") var favouriteOrder: Int?,
|
@SerialName("favouriteOrder") var favouriteOrder: Int?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class CharacterName(
|
data class CharacterName(
|
||||||
|
@ -109,7 +109,7 @@ data class CharacterName(
|
||||||
|
|
||||||
// The currently authenticated users preferred name language. Default romaji for non-authenticated
|
// The currently authenticated users preferred name language. Default romaji for non-authenticated
|
||||||
@SerialName("userPreferred") var userPreferred: String?,
|
@SerialName("userPreferred") var userPreferred: String?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class CharacterImage(
|
data class CharacterImage(
|
||||||
|
@ -118,4 +118,4 @@ data class CharacterImage(
|
||||||
|
|
||||||
// The character's image of media at medium size
|
// The character's image of media at medium size
|
||||||
@SerialName("medium") var medium: String?,
|
@SerialName("medium") var medium: String?,
|
||||||
)
|
) : java.io.Serializable
|
|
@ -143,7 +143,7 @@ class Query {
|
||||||
data class ToggleFollow(
|
data class ToggleFollow(
|
||||||
@SerialName("data")
|
@SerialName("data")
|
||||||
val data: Data?
|
val data: Data?
|
||||||
) {
|
) : java.io.Serializable {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Data(
|
data class Data(
|
||||||
@SerialName("ToggleFollow")
|
@SerialName("ToggleFollow")
|
||||||
|
@ -156,7 +156,7 @@ class Query {
|
||||||
data class GenreCollection(
|
data class GenreCollection(
|
||||||
@SerialName("data")
|
@SerialName("data")
|
||||||
val data: Data
|
val data: Data
|
||||||
) {
|
) : java.io.Serializable {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Data(
|
data class Data(
|
||||||
@SerialName("GenreCollection")
|
@SerialName("GenreCollection")
|
||||||
|
@ -168,7 +168,7 @@ class Query {
|
||||||
data class MediaTagCollection(
|
data class MediaTagCollection(
|
||||||
@SerialName("data")
|
@SerialName("data")
|
||||||
val data: Data
|
val data: Data
|
||||||
) {
|
) : java.io.Serializable {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Data(
|
data class Data(
|
||||||
@SerialName("MediaTagCollection")
|
@SerialName("MediaTagCollection")
|
||||||
|
@ -180,7 +180,7 @@ class Query {
|
||||||
data class User(
|
data class User(
|
||||||
@SerialName("data")
|
@SerialName("data")
|
||||||
val data: Data
|
val data: Data
|
||||||
) {
|
) : java.io.Serializable {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Data(
|
data class Data(
|
||||||
@SerialName("User")
|
@SerialName("User")
|
||||||
|
@ -192,7 +192,7 @@ class Query {
|
||||||
data class UserProfileResponse(
|
data class UserProfileResponse(
|
||||||
@SerialName("data")
|
@SerialName("data")
|
||||||
val data: Data
|
val data: Data
|
||||||
) {
|
) : java.io.Serializable {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Data(
|
data class Data(
|
||||||
@SerialName("user")
|
@SerialName("user")
|
||||||
|
@ -218,7 +218,7 @@ class Query {
|
||||||
val isFollower: Boolean,
|
val isFollower: Boolean,
|
||||||
@SerialName("isBlocked")
|
@SerialName("isBlocked")
|
||||||
val isBlocked: Boolean,
|
val isBlocked: Boolean,
|
||||||
@SerialName("favorites")
|
@SerialName("favourites")
|
||||||
val favorites: UserFavorites?,
|
val favorites: UserFavorites?,
|
||||||
@SerialName("statistics")
|
@SerialName("statistics")
|
||||||
val statistics: NNUserStatisticTypes,
|
val statistics: NNUserStatisticTypes,
|
||||||
|
@ -326,6 +326,8 @@ class Query {
|
||||||
val id: Int,
|
val id: Int,
|
||||||
@SerialName("name")
|
@SerialName("name")
|
||||||
val name: String,
|
val name: String,
|
||||||
|
@SerialName("mediaListOptions")
|
||||||
|
val mediaListOptions: MediaListOptions,
|
||||||
@SerialName("statistics")
|
@SerialName("statistics")
|
||||||
val statistics: StatisticsTypes
|
val statistics: StatisticsTypes
|
||||||
)
|
)
|
||||||
|
|
|
@ -251,7 +251,7 @@ data class MediaCoverImage(
|
||||||
|
|
||||||
// Average #hex color of cover image
|
// Average #hex color of cover image
|
||||||
@SerialName("color") var color: String?,
|
@SerialName("color") var color: String?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MediaList(
|
data class MediaList(
|
||||||
|
@ -490,7 +490,7 @@ data class MediaExternalLink(
|
||||||
|
|
||||||
// isDisabled: Boolean
|
// isDisabled: Boolean
|
||||||
@SerialName("notes") var notes: String?,
|
@SerialName("notes") var notes: String?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class ExternalLinkType {
|
enum class ExternalLinkType {
|
||||||
|
@ -512,13 +512,13 @@ data class MediaListCollection(
|
||||||
// If there is another chunk
|
// If there is another chunk
|
||||||
@SerialName("hasNextChunk") var hasNextChunk: Boolean?,
|
@SerialName("hasNextChunk") var hasNextChunk: Boolean?,
|
||||||
|
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class FollowData(
|
data class FollowData(
|
||||||
@SerialName("id") var id: Int,
|
@SerialName("id") var id: Int,
|
||||||
@SerialName("isFollowing") var isFollowing: Boolean,
|
@SerialName("isFollowing") var isFollowing: Boolean,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MediaListGroup(
|
data class MediaListGroup(
|
||||||
|
@ -532,4 +532,4 @@ data class MediaListGroup(
|
||||||
@SerialName("isSplitCompletedList") var isSplitCompletedList: Boolean?,
|
@SerialName("isSplitCompletedList") var isSplitCompletedList: Boolean?,
|
||||||
|
|
||||||
@SerialName("status") var status: MediaListStatus?,
|
@SerialName("status") var status: MediaListStatus?,
|
||||||
)
|
) : java.io.Serializable
|
|
@ -164,7 +164,7 @@ data class Favourites(
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MediaListOptions(
|
data class MediaListOptions(
|
||||||
// The score format the user is using for media lists
|
// The score format the user is using for media lists
|
||||||
// @SerialName("scoreFormat") var scoreFormat: ScoreFormat?,
|
@SerialName("scoreFormat") var scoreFormat: String?,
|
||||||
|
|
||||||
// The default order list rows should be displayed in
|
// The default order list rows should be displayed in
|
||||||
@SerialName("rowOrder") var rowOrder: String?,
|
@SerialName("rowOrder") var rowOrder: String?,
|
||||||
|
|
|
@ -1245,10 +1245,10 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
|
||||||
media.anime!!.selectedEpisode!!
|
media.anime!!.selectedEpisode!!
|
||||||
)
|
)
|
||||||
|
|
||||||
val list = PrefManager.getVal<Set<String>>(PrefName.ContinuedAnimeSet).toMutableList()
|
val list = (PrefManager.getNullableCustomVal("continueAnimeList", listOf<Int>(), List::class.java) as List<Int>).toMutableList()
|
||||||
if (list.contains(media.id.toString())) list.remove(media.id.toString())
|
if (list.contains(media.id)) list.remove(media.id)
|
||||||
list.add(media.id.toString())
|
list.add(media.id)
|
||||||
PrefManager.setVal(PrefName.ContinuedAnimeSet, list.toSet())
|
PrefManager.setCustomVal("continueAnimeList", list)
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
extractor?.onVideoStopped(video)
|
extractor?.onVideoStopped(video)
|
||||||
|
|
|
@ -18,7 +18,6 @@ import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAScrollablePlotAre
|
||||||
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAStyle
|
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAStyle
|
||||||
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAYAxis
|
import com.github.aachartmodel.aainfographics.aaoptionsmodel.AAYAxis
|
||||||
import com.github.aachartmodel.aainfographics.aatools.AAColor
|
import com.github.aachartmodel.aainfographics.aatools.AAColor
|
||||||
import com.github.aachartmodel.aainfographics.aatools.AAGradientColor
|
|
||||||
|
|
||||||
class ChartBuilder {
|
class ChartBuilder {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -37,7 +36,7 @@ class ChartBuilder {
|
||||||
data class ChartPacket(
|
data class ChartPacket(
|
||||||
val username: String,
|
val username: String,
|
||||||
val names: List<Any>,
|
val names: List<Any>,
|
||||||
val statData: List<Number>
|
var statData: List<Number>
|
||||||
)
|
)
|
||||||
|
|
||||||
fun buildChart(
|
fun buildChart(
|
||||||
|
@ -47,11 +46,12 @@ class ChartBuilder {
|
||||||
statType: StatType,
|
statType: StatType,
|
||||||
mediaType: MediaType,
|
mediaType: MediaType,
|
||||||
chartPackets: List<ChartPacket>,
|
chartPackets: List<ChartPacket>,
|
||||||
xAxisName: String = "X Axis",
|
xAxisName: String,
|
||||||
xAxisTickInterval: Int? = null,
|
xAxisTickInterval: Int? = null,
|
||||||
polar: Boolean = false,
|
polar: Boolean = false,
|
||||||
passedCategories: List<String>? = null,
|
passedCategories: List<String>? = null,
|
||||||
scrollPos: Float? = null,
|
scrollPos: Float? = null,
|
||||||
|
normalize: Boolean = false
|
||||||
): AAOptions {
|
): AAOptions {
|
||||||
val typedValue = TypedValue()
|
val typedValue = TypedValue()
|
||||||
context.theme.resolveAttribute(
|
context.theme.resolveAttribute(
|
||||||
|
@ -69,6 +69,11 @@ class ChartBuilder {
|
||||||
aaChartType = AAChartType.Column
|
aaChartType = AAChartType.Column
|
||||||
categories = chartPackets[0].names.map { it.toString() }
|
categories = chartPackets[0].names.map { it.toString() }
|
||||||
}
|
}
|
||||||
|
if (normalize && chartPackets.size > 1) {
|
||||||
|
chartPackets.forEach {
|
||||||
|
it.statData = normalizeData(it.statData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val namesMax = chartPackets.maxOf { it.names.size }
|
val namesMax = chartPackets.maxOf { it.names.size }
|
||||||
val palette = ColorEditor.generateColorPalette(primaryColor, namesMax)
|
val palette = ColorEditor.generateColorPalette(primaryColor, namesMax)
|
||||||
|
@ -76,20 +81,25 @@ class ChartBuilder {
|
||||||
ChartType.OneDimensional -> {
|
ChartType.OneDimensional -> {
|
||||||
val chart = AAChartModel()
|
val chart = AAChartModel()
|
||||||
.chartType(aaChartType)
|
.chartType(aaChartType)
|
||||||
.subtitle(getTypeName(statType, mediaType))
|
.subtitle(
|
||||||
|
getTypeName(
|
||||||
|
statType,
|
||||||
|
mediaType
|
||||||
|
) + if (normalize && chartPackets.size > 1) " (Normalized)" else ""
|
||||||
|
)
|
||||||
.zoomType(AAChartZoomType.None)
|
.zoomType(AAChartZoomType.None)
|
||||||
.dataLabelsEnabled(true)
|
.dataLabelsEnabled(true)
|
||||||
val elements: MutableList<Any> = mutableListOf()
|
val elements: MutableList<Any> = mutableListOf()
|
||||||
chartPackets.forEachIndexed { index, chartPacket ->
|
chartPackets.forEachIndexed { index, chartPacket ->
|
||||||
val element = AASeriesElement()
|
val element = AASeriesElement()
|
||||||
.name(chartPacket.username)
|
.name(chartPacket.username)
|
||||||
.data(
|
.data(
|
||||||
get1DElements(
|
get1DElements(
|
||||||
chartPacket.names,
|
chartPacket.names,
|
||||||
chartPacket.statData,
|
chartPacket.statData,
|
||||||
palette
|
palette
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
element.color(primaryColor)
|
element.color(primaryColor)
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,31 +119,66 @@ class ChartBuilder {
|
||||||
palette.map { String.format("#%06X", 0xFFFFFF and it) }.toTypedArray()
|
palette.map { String.format("#%06X", 0xFFFFFF and it) }.toTypedArray()
|
||||||
val chart = AAChartModel()
|
val chart = AAChartModel()
|
||||||
.chartType(aaChartType)
|
.chartType(aaChartType)
|
||||||
.subtitle(getTypeName(statType, mediaType))
|
.subtitle(
|
||||||
|
getTypeName(
|
||||||
|
statType,
|
||||||
|
mediaType
|
||||||
|
) + if (normalize && chartPackets.size > 1) " (Normalized)" else ""
|
||||||
|
)
|
||||||
.zoomType(AAChartZoomType.None)
|
.zoomType(AAChartZoomType.None)
|
||||||
.dataLabelsEnabled(false)
|
.dataLabelsEnabled(false)
|
||||||
.yAxisTitle(getTypeName(statType, mediaType))
|
.yAxisTitle(
|
||||||
if (chartPackets.size == 1) {
|
getTypeName(
|
||||||
chart.colorsTheme(hexColorsArray)
|
statType,
|
||||||
}
|
mediaType
|
||||||
|
) + if (normalize && chartPackets.size > 1) " (Normalized)" else ""
|
||||||
|
)
|
||||||
|
if (chartPackets.size == 1) {
|
||||||
|
chart.colorsTheme(hexColorsArray)
|
||||||
|
}
|
||||||
|
|
||||||
val elements: MutableList<AASeriesElement> = mutableListOf()
|
val elements: MutableList<AASeriesElement> = mutableListOf()
|
||||||
chartPackets.forEachIndexed { index, chartPacket ->
|
chartPackets.forEachIndexed { index, chartPacket ->
|
||||||
val element = get2DElements(
|
val element = get2DElements(
|
||||||
chartPacket.names,
|
chartPacket.names,
|
||||||
chartPacket.statData,
|
chartPacket.statData,
|
||||||
chartPackets.size == 1
|
chartPackets.size == 1
|
||||||
)
|
)
|
||||||
element.name(chartPacket.username)
|
element.name(chartPacket.username)
|
||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
element.color(AAColor.rgbaColor(Color.red(primaryColor), Color.green(primaryColor), Color.blue(primaryColor), 0.9f))
|
element.color(
|
||||||
|
AAColor.rgbaColor(
|
||||||
|
Color.red(primaryColor),
|
||||||
|
Color.green(primaryColor),
|
||||||
|
Color.blue(primaryColor),
|
||||||
|
0.9f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
element.color(AAColor.rgbaColor(Color.red(ColorEditor.oppositeColor(primaryColor)), Color.green(ColorEditor.oppositeColor(primaryColor)), Color.blue(ColorEditor.oppositeColor(primaryColor)), 0.9f))
|
element.color(
|
||||||
|
AAColor.rgbaColor(
|
||||||
|
Color.red(
|
||||||
|
ColorEditor.oppositeColor(
|
||||||
|
primaryColor
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Color.green(ColorEditor.oppositeColor(primaryColor)),
|
||||||
|
Color.blue(ColorEditor.oppositeColor(primaryColor)),
|
||||||
|
0.9f
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (chartPackets.size == 1) {
|
if (chartPackets.size == 1) {
|
||||||
element.fillColor(AAColor.rgbaColor(Color.red(primaryColor), Color.green(primaryColor), Color.blue(primaryColor), 0.9f))
|
element.fillColor(
|
||||||
|
AAColor.rgbaColor(
|
||||||
|
Color.red(primaryColor),
|
||||||
|
Color.green(primaryColor),
|
||||||
|
Color.blue(primaryColor),
|
||||||
|
0.9f
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
elements.add(element)
|
elements.add(element)
|
||||||
}
|
}
|
||||||
|
@ -205,12 +250,12 @@ class ChartBuilder {
|
||||||
statValues.add(arrayOf(names[i], statData[i], statData[i]))
|
statValues.add(arrayOf(names[i], statData[i], statData[i]))
|
||||||
}
|
}
|
||||||
return AASeriesElement()
|
return AASeriesElement()
|
||||||
.data(statValues.toTypedArray())
|
.data(statValues.toTypedArray())
|
||||||
.dataLabels(
|
.dataLabels(
|
||||||
AADataLabels()
|
AADataLabels()
|
||||||
.enabled(false)
|
.enabled(false)
|
||||||
)
|
)
|
||||||
.colorByPoint(colorByPoint)
|
.colorByPoint(colorByPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun get1DElements(
|
private fun get1DElements(
|
||||||
|
@ -255,6 +300,14 @@ class ChartBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun normalizeData(data: List<Number>): List<Number> {
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
val max = data.maxOf { it.toDouble() }
|
||||||
|
return data.map { (it.toDouble() / max) * 100 }
|
||||||
|
}
|
||||||
|
|
||||||
private fun setColors(aaOptions: AAOptions, context: Context, primaryColor: Int) {
|
private fun setColors(aaOptions: AAOptions, context: Context, primaryColor: Int) {
|
||||||
val backgroundColor = TypedValue()
|
val backgroundColor = TypedValue()
|
||||||
context.theme.resolveAttribute(
|
context.theme.resolveAttribute(
|
||||||
|
@ -281,7 +334,7 @@ class ChartBuilder {
|
||||||
Color.red(colorOnBackground.data),
|
Color.red(colorOnBackground.data),
|
||||||
Color.green(colorOnBackground.data),
|
Color.green(colorOnBackground.data),
|
||||||
Color.blue(colorOnBackground.data),
|
Color.blue(colorOnBackground.data),
|
||||||
0.9f
|
1.0f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -292,7 +345,7 @@ class ChartBuilder {
|
||||||
Color.red(backgroundColor.data),
|
Color.red(backgroundColor.data),
|
||||||
Color.green(backgroundColor.data),
|
Color.green(backgroundColor.data),
|
||||||
Color.blue(backgroundColor.data),
|
Color.blue(backgroundColor.data),
|
||||||
0.9f
|
1.0f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
aaOptions.title?.style(onBackgroundStyle)
|
aaOptions.title?.style(onBackgroundStyle)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ani.dantotsu.profile
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -13,7 +14,6 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.buildMarkwon
|
|
||||||
import ani.dantotsu.connections.anilist.ProfileViewModel
|
import ani.dantotsu.connections.anilist.ProfileViewModel
|
||||||
import ani.dantotsu.connections.anilist.api.Query
|
import ani.dantotsu.connections.anilist.api.Query
|
||||||
import ani.dantotsu.databinding.FragmentProfileBinding
|
import ani.dantotsu.databinding.FragmentProfileBinding
|
||||||
|
@ -23,10 +23,12 @@ import ani.dantotsu.media.MediaAdaptor
|
||||||
import ani.dantotsu.media.user.ListActivity
|
import ani.dantotsu.media.user.ListActivity
|
||||||
import ani.dantotsu.setSlideIn
|
import ani.dantotsu.setSlideIn
|
||||||
import ani.dantotsu.setSlideUp
|
import ani.dantotsu.setSlideUp
|
||||||
|
import ani.dantotsu.util.ColorEditor.Companion.toCssColor
|
||||||
import kotlinx.coroutines.Dispatchers
|
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
|
||||||
|
@ -44,8 +46,34 @@ class ProfileFragment(): Fragment() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
activity = requireActivity() as ProfileActivity
|
activity = requireActivity() as ProfileActivity
|
||||||
user = arguments?.getSerializable("user") as Query.UserProfile
|
user = arguments?.getSerializable("user") as Query.UserProfile
|
||||||
val markwon = buildMarkwon(activity, false)
|
|
||||||
markwon.setMarkdown(binding.profileUserBio, user.about?:"")
|
val backGroundColorTypedValue = TypedValue()
|
||||||
|
val textColorTypedValue = TypedValue()
|
||||||
|
activity.theme.resolveAttribute(
|
||||||
|
android.R.attr.windowBackground,
|
||||||
|
backGroundColorTypedValue,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
activity.theme.resolveAttribute(
|
||||||
|
com.google.android.material.R.attr.colorOnBackground,
|
||||||
|
textColorTypedValue,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.profileUserBio.settings.loadWithOverviewMode = true
|
||||||
|
binding.profileUserBio.settings.useWideViewPort = true
|
||||||
|
binding.profileUserBio.setInitialScale(1)
|
||||||
|
binding.profileUserBio.loadDataWithBaseURL(
|
||||||
|
null,
|
||||||
|
styled(
|
||||||
|
convertMarkdownToHtml(user.about ?: ""),
|
||||||
|
backGroundColorTypedValue.data,
|
||||||
|
textColorTypedValue.data
|
||||||
|
),
|
||||||
|
"text/html; charset=utf-8",
|
||||||
|
"UTF-8",
|
||||||
|
null
|
||||||
|
)
|
||||||
binding.userInfoContainer.visibility = if (user.about != null) View.VISIBLE else View.GONE
|
binding.userInfoContainer.visibility = if (user.about != null) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
binding.profileAnimeList.setOnClickListener {
|
binding.profileAnimeList.setOnClickListener {
|
||||||
|
@ -67,7 +95,8 @@ class ProfileFragment(): Fragment() {
|
||||||
binding.profileAnimeListImage.loadImage("https://bit.ly/31bsIHq")
|
binding.profileAnimeListImage.loadImage("https://bit.ly/31bsIHq")
|
||||||
binding.profileMangaListImage.loadImage("https://bit.ly/2ZGfcuG")
|
binding.profileMangaListImage.loadImage("https://bit.ly/2ZGfcuG")
|
||||||
binding.statsEpisodesWatched.text = user.statistics.anime.episodesWatched.toString()
|
binding.statsEpisodesWatched.text = user.statistics.anime.episodesWatched.toString()
|
||||||
binding.statsDaysWatched.text = (user.statistics.anime.minutesWatched / (24 * 60)).toString()
|
binding.statsDaysWatched.text =
|
||||||
|
(user.statistics.anime.minutesWatched / (24 * 60)).toString()
|
||||||
binding.statsTotalAnime.text = user.statistics.anime.count.toString()
|
binding.statsTotalAnime.text = user.statistics.anime.count.toString()
|
||||||
binding.statsAnimeMeanScore.text = user.statistics.anime.meanScore.toString()
|
binding.statsAnimeMeanScore.text = user.statistics.anime.meanScore.toString()
|
||||||
binding.statsChaptersRead.text = user.statistics.manga.chaptersRead.toString()
|
binding.statsChaptersRead.text = user.statistics.manga.chaptersRead.toString()
|
||||||
|
@ -80,7 +109,7 @@ class ProfileFragment(): Fragment() {
|
||||||
model.setAnimeFav(user.id)
|
model.setAnimeFav(user.id)
|
||||||
model.setMangaFav(user.id)
|
model.setMangaFav(user.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
initRecyclerView(
|
initRecyclerView(
|
||||||
model.getAnimeFav(),
|
model.getAnimeFav(),
|
||||||
binding.profileFavAnimeContainer,
|
binding.profileFavAnimeContainer,
|
||||||
|
@ -89,7 +118,7 @@ class ProfileFragment(): Fragment() {
|
||||||
binding.profileFavAnimeEmpty,
|
binding.profileFavAnimeEmpty,
|
||||||
binding.profileFavAnime
|
binding.profileFavAnime
|
||||||
)
|
)
|
||||||
|
|
||||||
initRecyclerView(
|
initRecyclerView(
|
||||||
model.getMangaFav(),
|
model.getMangaFav(),
|
||||||
binding.profileFavMangaContainer,
|
binding.profileFavMangaContainer,
|
||||||
|
@ -107,6 +136,16 @@ class ProfileFragment(): Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun convertMarkdownToHtml(markdown: String): String {
|
||||||
|
val regex = """\[\!\[(.*?)\]\((.*?)\)\]\((.*?)\)""".toRegex()
|
||||||
|
return regex.replace(markdown) { matchResult ->
|
||||||
|
val altText = matchResult.groupValues[1]
|
||||||
|
val imageUrl = matchResult.groupValues[2]
|
||||||
|
val linkUrl = matchResult.groupValues[3]
|
||||||
|
"""<a href="$linkUrl"><img src="$imageUrl" alt="$altText"></a>"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun initRecyclerView(
|
private fun initRecyclerView(
|
||||||
mode: LiveData<ArrayList<Media>>,
|
mode: LiveData<ArrayList<Media>>,
|
||||||
container: View,
|
container: View,
|
||||||
|
@ -146,6 +185,37 @@ class ProfileFragment(): Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun styled(html: String, backGroundColor: Int, textColor: Int): String {
|
||||||
|
return """
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, charset=UTF-8">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: ${backGroundColor.toCssColor()};
|
||||||
|
color: ${textColor.toCssColor()};
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow-x: hidden; /* Prevent horizontal scrolling */
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto; /* Maintain aspect ratio */
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: ${textColor.toCssColor()};
|
||||||
|
}
|
||||||
|
/* Add responsive design elements for other content as needed */
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
$html
|
||||||
|
</body>
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(query: Query.UserProfile): ProfileFragment {
|
fun newInstance(query: Query.UserProfile): ProfileFragment {
|
||||||
val args = Bundle().apply {
|
val args = Bundle().apply {
|
||||||
|
|
|
@ -12,10 +12,10 @@ import ani.dantotsu.R
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.api.Query
|
import ani.dantotsu.connections.anilist.api.Query
|
||||||
import ani.dantotsu.databinding.FragmentStatisticsBinding
|
import ani.dantotsu.databinding.FragmentStatisticsBinding
|
||||||
import ani.dantotsu.profile.ChartBuilder.Companion.ChartType
|
|
||||||
import ani.dantotsu.profile.ChartBuilder.Companion.StatType
|
|
||||||
import ani.dantotsu.profile.ChartBuilder.Companion.MediaType
|
|
||||||
import ani.dantotsu.profile.ChartBuilder.Companion.ChartPacket
|
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 com.github.aachartmodel.aainfographics.aachartcreator.AAChartType
|
import com.github.aachartmodel.aainfographics.aachartcreator.AAChartType
|
||||||
import com.xwray.groupie.GroupieAdapter
|
import com.xwray.groupie.GroupieAdapter
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -147,7 +147,7 @@ class StatsFragment :
|
||||||
|
|
||||||
private fun loadFormatChart(anime: Boolean) {
|
private fun loadFormatChart(anime: Boolean) {
|
||||||
val chartPackets = mutableListOf<ChartPacket>()
|
val chartPackets = mutableListOf<ChartPacket>()
|
||||||
stats.forEach {stat ->
|
stats.forEach { stat ->
|
||||||
val names: List<String> = if (anime) {
|
val names: List<String> = if (anime) {
|
||||||
stat?.statistics?.anime?.formats?.map { it.format } ?: emptyList()
|
stat?.statistics?.anime?.formats?.map { it.format } ?: emptyList()
|
||||||
} else {
|
} else {
|
||||||
|
@ -167,7 +167,7 @@ class StatsFragment :
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
}
|
}
|
||||||
if (names.isNotEmpty() && values.isNotEmpty()) {
|
if (names.isNotEmpty() && values.isNotEmpty()) {
|
||||||
chartPackets.add(ChartPacket(stat?.name?:"Unknown", names, values))
|
chartPackets.add(ChartPacket(stat?.name ?: "Unknown", names, values))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chartPackets.isNotEmpty()) {
|
if (chartPackets.isNotEmpty()) {
|
||||||
|
@ -178,6 +178,7 @@ class StatsFragment :
|
||||||
statType,
|
statType,
|
||||||
type,
|
type,
|
||||||
chartPackets,
|
chartPackets,
|
||||||
|
xAxisName = "Format",
|
||||||
)
|
)
|
||||||
adapter.add(ChartItem("Format", formatChart, activity))
|
adapter.add(ChartItem("Format", formatChart, activity))
|
||||||
}
|
}
|
||||||
|
@ -215,7 +216,8 @@ class StatsFragment :
|
||||||
AAChartType.Funnel,
|
AAChartType.Funnel,
|
||||||
statType,
|
statType,
|
||||||
type,
|
type,
|
||||||
chartPackets
|
chartPackets,
|
||||||
|
xAxisName = "Status",
|
||||||
)
|
)
|
||||||
adapter.add(ChartItem("Status", statusChart, activity))
|
adapter.add(ChartItem("Status", statusChart, activity))
|
||||||
}
|
}
|
||||||
|
@ -225,9 +227,19 @@ class StatsFragment :
|
||||||
val chartPackets = mutableListOf<ChartPacket>()
|
val chartPackets = mutableListOf<ChartPacket>()
|
||||||
stats.forEach { stat ->
|
stats.forEach { stat ->
|
||||||
val names: List<Int> = if (anime) {
|
val names: List<Int> = if (anime) {
|
||||||
stat?.statistics?.anime?.scores?.map { it.score } ?: emptyList()
|
stat?.statistics?.anime?.scores?.map {
|
||||||
|
convertScore(
|
||||||
|
it.score,
|
||||||
|
stat.mediaListOptions.scoreFormat
|
||||||
|
)
|
||||||
|
} ?: emptyList()
|
||||||
} else {
|
} else {
|
||||||
stat?.statistics?.manga?.scores?.map { it.score } ?: emptyList()
|
stat?.statistics?.manga?.scores?.map {
|
||||||
|
convertScore(
|
||||||
|
it.score,
|
||||||
|
stat.mediaListOptions.scoreFormat
|
||||||
|
)
|
||||||
|
} ?: emptyList()
|
||||||
}
|
}
|
||||||
val values: List<Number> = if (anime) {
|
val values: List<Number> = if (anime) {
|
||||||
when (statType) {
|
when (statType) {
|
||||||
|
@ -337,6 +349,7 @@ class StatsFragment :
|
||||||
type,
|
type,
|
||||||
chartPackets,
|
chartPackets,
|
||||||
xAxisName = "Year",
|
xAxisName = "Year",
|
||||||
|
scrollPos = 0.0f
|
||||||
)
|
)
|
||||||
adapter.add(ChartItem("Release Year", releaseYearChart, activity))
|
adapter.add(ChartItem("Release Year", releaseYearChart, activity))
|
||||||
}
|
}
|
||||||
|
@ -429,6 +442,7 @@ class StatsFragment :
|
||||||
xAxisName = "Genre",
|
xAxisName = "Genre",
|
||||||
polar = true,
|
polar = true,
|
||||||
passedCategories = chartPackets[0].names as List<String>,
|
passedCategories = chartPackets[0].names as List<String>,
|
||||||
|
normalize = true
|
||||||
)
|
)
|
||||||
adapter.add(ChartItem("Genre", genreChart, activity))
|
adapter.add(ChartItem("Genre", genreChart, activity))
|
||||||
}
|
}
|
||||||
|
@ -546,9 +560,11 @@ class StatsFragment :
|
||||||
val chartPackets = mutableListOf<ChartPacket>()
|
val chartPackets = mutableListOf<ChartPacket>()
|
||||||
stats.forEach { stat ->
|
stats.forEach { stat ->
|
||||||
val names: List<String> = if (anime) {
|
val names: List<String> = if (anime) {
|
||||||
stat?.statistics?.anime?.voiceActors?.map { it.voiceActor.name.full?:"unknown" } ?: emptyList()
|
stat?.statistics?.anime?.voiceActors?.map { it.voiceActor.name.full ?: "unknown" }
|
||||||
|
?: emptyList()
|
||||||
} else {
|
} else {
|
||||||
stat?.statistics?.manga?.voiceActors?.map { it.voiceActor.name.full?:"unknown" } ?: emptyList()
|
stat?.statistics?.manga?.voiceActors?.map { it.voiceActor.name.full ?: "unknown" }
|
||||||
|
?: emptyList()
|
||||||
}
|
}
|
||||||
val values: List<Number> = if (anime) {
|
val values: List<Number> = if (anime) {
|
||||||
when (statType) {
|
when (statType) {
|
||||||
|
@ -644,7 +660,8 @@ class StatsFragment :
|
||||||
xAxisName = "Studio",
|
xAxisName = "Studio",
|
||||||
polar = true,
|
polar = true,
|
||||||
passedCategories = chartPackets[0].names as List<String>,
|
passedCategories = chartPackets[0].names as List<String>,
|
||||||
scrollPos = null
|
scrollPos = null,
|
||||||
|
normalize = true
|
||||||
)
|
)
|
||||||
adapter.add(ChartItem("Studio", studioChart, activity))
|
adapter.add(ChartItem("Studio", studioChart, activity))
|
||||||
}
|
}
|
||||||
|
@ -654,9 +671,11 @@ class StatsFragment :
|
||||||
val chartPackets = mutableListOf<ChartPacket>()
|
val chartPackets = mutableListOf<ChartPacket>()
|
||||||
stats.forEach { stat ->
|
stats.forEach { stat ->
|
||||||
val names: List<String> = if (anime) {
|
val names: List<String> = if (anime) {
|
||||||
stat?.statistics?.anime?.staff?.map { it.staff.name.full?:"unknown" } ?: emptyList()
|
stat?.statistics?.anime?.staff?.map { it.staff.name.full ?: "unknown" }
|
||||||
|
?: emptyList()
|
||||||
} else {
|
} else {
|
||||||
stat?.statistics?.manga?.staff?.map { it.staff.name.full?:"unknown" } ?: emptyList()
|
stat?.statistics?.manga?.staff?.map { it.staff.name.full ?: "unknown" }
|
||||||
|
?: emptyList()
|
||||||
}
|
}
|
||||||
val values: List<Number> = if (anime) {
|
val values: List<Number> = if (anime) {
|
||||||
when (statType) {
|
when (statType) {
|
||||||
|
@ -704,6 +723,17 @@ class StatsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun convertScore(score: Int, type: String?): Int {
|
||||||
|
return when (type) {
|
||||||
|
"POINT_100" -> score
|
||||||
|
"POINT_10_DECIMAL" -> score
|
||||||
|
"POINT_10" -> score * 10
|
||||||
|
"POINT_5" -> score * 20
|
||||||
|
"POINT_3" -> score * 33
|
||||||
|
else -> score
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(user: Query.UserProfile): StatsFragment {
|
fun newInstance(user: Query.UserProfile): StatsFragment {
|
||||||
val args = Bundle().apply {
|
val args = Bundle().apply {
|
||||||
|
|
|
@ -100,7 +100,6 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
|
||||||
UseInternalCast(Pref(Location.Player, Boolean::class, false)),
|
UseInternalCast(Pref(Location.Player, Boolean::class, false)),
|
||||||
Pip(Pref(Location.Player, Boolean::class, true)),
|
Pip(Pref(Location.Player, Boolean::class, true)),
|
||||||
RotationPlayer(Pref(Location.Player, Boolean::class, true)),
|
RotationPlayer(Pref(Location.Player, Boolean::class, true)),
|
||||||
ContinuedAnimeSet(Pref(Location.Player, Set::class, setOf<String>())),
|
|
||||||
|
|
||||||
//Reader
|
//Reader
|
||||||
ShowSource(Pref(Location.Reader, Boolean::class, true)),
|
ShowSource(Pref(Location.Reader, Boolean::class, true)),
|
||||||
|
|
|
@ -84,5 +84,14 @@ class ColorEditor {
|
||||||
}
|
}
|
||||||
return adjustedColor
|
return adjustedColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Int.toCssColor(): String {
|
||||||
|
var base = "rgba("
|
||||||
|
base += "${Color.red(this)}, "
|
||||||
|
base += "${Color.green(this)}, "
|
||||||
|
base += "${Color.blue(this)}, "
|
||||||
|
base += "${Color.alpha(this) / 255.0})"
|
||||||
|
return base
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -332,7 +332,7 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/userInfoContainer"
|
android:id="@+id/userInfoContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -347,12 +347,13 @@
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<TextView
|
<WebView
|
||||||
android:id="@+id/profileUserBio"
|
android:id="@+id/profileUserBio"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
|
android:textAlignment="textStart"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
tools:text="@string/slogan" />
|
tools:text="@string/slogan" />
|
||||||
|
|
|
@ -226,7 +226,7 @@
|
||||||
|
|
||||||
<!-- theme 4 -->
|
<!-- theme 4 -->
|
||||||
<color name="seed_4">#e800ac</color>
|
<color name="seed_4">#e800ac</color>
|
||||||
<color name="md_theme_light_4_primary">#B30084</color>
|
<color name="md_theme_light_4_primary">#FF92E2</color>
|
||||||
<color name="md_theme_light_4_onPrimary">#FFFFFF</color>
|
<color name="md_theme_light_4_onPrimary">#FFFFFF</color>
|
||||||
<color name="md_theme_light_4_primaryContainer">#FFD8EA</color>
|
<color name="md_theme_light_4_primaryContainer">#FFD8EA</color>
|
||||||
<color name="md_theme_light_4_onPrimaryContainer">#3C002A</color>
|
<color name="md_theme_light_4_onPrimaryContainer">#3C002A</color>
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
<style name="Theme.Dantotsu.PopupOverlay" parent="Theme.Dantotsu" />
|
<style name="Theme.Dantotsu.PopupOverlay" parent="Theme.Dantotsu" />
|
||||||
|
|
||||||
<style name="Theme.Dantotsu.NeverCutout" parent="@style/Theme.Dantotsu.NoActionBar">
|
<style name="Theme.Dantotsu.NeverCutout" parent="@style/Theme.Dantotsu.NoActionBar">
|
||||||
<item name="android:navigationBarColor">@color/nav_bg</item>
|
<item name="android:navigationBarColor">?android:colorBackground</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Dantotsu.ALLBLACK" parent="Theme.Base">
|
<style name="Theme.Dantotsu.ALLBLACK" parent="Theme.Base">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue