mirror of
https://github.com/rebelonion/Dantotsu.git
synced 2026-01-29 10:01:01 +00:00
Merge branch 'dev' into dev
This commit is contained in:
@@ -202,7 +202,7 @@
|
||||
android:parentActivityName=".MainActivity" />
|
||||
<activity
|
||||
android:name=".util.ActivityMarkdownCreator"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
android:windowSoftInputMode="adjustResize|stateVisible" />
|
||||
<activity android:name=".parsers.ParserTestActivity" />
|
||||
<activity
|
||||
android:name=".media.ReviewActivity"
|
||||
|
||||
@@ -313,7 +313,6 @@ class MainActivity : AppCompatActivity() {
|
||||
mainViewPager.adapter =
|
||||
ViewPagerAdapter(supportFragmentManager, lifecycle)
|
||||
mainViewPager.setPageTransformer(ZoomOutPageTransformer())
|
||||
mainViewPager.offscreenPageLimit = 1
|
||||
navbar.selectTabAt(selectedOption)
|
||||
navbar.setOnTabSelectListener(object :
|
||||
AnimatedBottomBar.OnTabSelectListener {
|
||||
|
||||
@@ -6,14 +6,14 @@ import ani.dantotsu.checkGenreTime
|
||||
import ani.dantotsu.checkId
|
||||
import ani.dantotsu.connections.anilist.Anilist.authorRoles
|
||||
import ani.dantotsu.connections.anilist.Anilist.executeQuery
|
||||
import ani.dantotsu.connections.anilist.api.Activity
|
||||
import ani.dantotsu.connections.anilist.api.FeedResponse
|
||||
import ani.dantotsu.connections.anilist.api.FuzzyDate
|
||||
import ani.dantotsu.connections.anilist.api.MediaEdge
|
||||
import ani.dantotsu.connections.anilist.api.MediaList
|
||||
import ani.dantotsu.connections.anilist.api.NotificationResponse
|
||||
import ani.dantotsu.connections.anilist.api.Page
|
||||
import ani.dantotsu.connections.anilist.api.Query
|
||||
import ani.dantotsu.connections.anilist.api.ReplyResponse
|
||||
import ani.dantotsu.connections.anilist.api.ToggleLike
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.logError
|
||||
@@ -28,6 +28,7 @@ import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
@@ -422,9 +423,7 @@ class AnilistQueries {
|
||||
val toShow: List<Boolean> =
|
||||
PrefManager.getVal(PrefName.HomeLayout)
|
||||
if (toShow.getOrNull(7) != true) return null
|
||||
var query = """{"""
|
||||
query += "Page1:${status(1)}Page2:${status(2)}"
|
||||
query += """}""".trimEnd(',')
|
||||
val query = """{Page1:${status(1)}Page2:${status(2)}}"""
|
||||
val response = executeQuery<Query.HomePageMedia>(query, show = true)
|
||||
val list = mutableListOf<User>()
|
||||
val threeDaysAgo = Calendar.getInstance().apply {
|
||||
@@ -461,8 +460,9 @@ class AnilistQueries {
|
||||
}
|
||||
}
|
||||
|
||||
if (anilistActivities.isEmpty() && Anilist.token != null){
|
||||
anilistActivities.add(0,
|
||||
if (anilistActivities.isEmpty() && Anilist.token != null) {
|
||||
anilistActivities.add(
|
||||
0,
|
||||
User(
|
||||
Anilist.userid!!,
|
||||
Anilist.username!!,
|
||||
@@ -477,206 +477,176 @@ class AnilistQueries {
|
||||
} else return null
|
||||
}
|
||||
|
||||
suspend fun initHomePage(): Map<String, ArrayList<*>> {
|
||||
suspend fun initHomePage(): Map<String, ArrayList<Media>> {
|
||||
val removeList = PrefManager.getCustomVal("removeList", setOf<Int>())
|
||||
val hidePrivate = PrefManager.getVal<Boolean>(PrefName.HidePrivate)
|
||||
val removedMedia = ArrayList<Media>()
|
||||
val toShow: List<Boolean> =
|
||||
PrefManager.getVal(PrefName.HomeLayout) // anime continue, anime fav, anime planned, manga continue, manga fav, manga planned, recommendations
|
||||
var query = """{"""
|
||||
if (toShow.getOrNull(0) == true) query += """currentAnime: ${
|
||||
continueMediaQuery(
|
||||
"ANIME",
|
||||
"CURRENT"
|
||||
)
|
||||
}, repeatingAnime: ${continueMediaQuery("ANIME", "REPEATING")}"""
|
||||
if (toShow.getOrNull(1) == true) query += """favoriteAnime: ${favMediaQuery(true, 1)}"""
|
||||
if (toShow.getOrNull(2) == true) query += """plannedAnime: ${
|
||||
continueMediaQuery(
|
||||
"ANIME",
|
||||
"PLANNING"
|
||||
)
|
||||
}"""
|
||||
if (toShow.getOrNull(3) == true) query += """currentManga: ${
|
||||
continueMediaQuery(
|
||||
"MANGA",
|
||||
"CURRENT"
|
||||
)
|
||||
}, repeatingManga: ${continueMediaQuery("MANGA", "REPEATING")}"""
|
||||
if (toShow.getOrNull(4) == true) query += """favoriteManga: ${favMediaQuery(false, 1)}"""
|
||||
if (toShow.getOrNull(5) == true) query += """plannedManga: ${
|
||||
continueMediaQuery(
|
||||
"MANGA",
|
||||
"PLANNING"
|
||||
)
|
||||
}"""
|
||||
if (toShow.getOrNull(6) == true) query += """recommendationQuery: ${recommendationQuery()}, recommendationPlannedQueryAnime: ${
|
||||
recommendationPlannedQuery(
|
||||
"ANIME"
|
||||
)
|
||||
}, recommendationPlannedQueryManga: ${recommendationPlannedQuery("MANGA")}"""
|
||||
query += """}""".trimEnd(',')
|
||||
PrefManager.getVal(PrefName.HomeLayout) // list of booleans for what to show
|
||||
|
||||
val queries = mutableListOf<String>()
|
||||
if (toShow.getOrNull(0) == true) {
|
||||
queries.add("""currentAnime: ${continueMediaQuery("ANIME", "CURRENT")}""")
|
||||
queries.add("""repeatingAnime: ${continueMediaQuery("ANIME", "REPEATING")}""")
|
||||
}
|
||||
if (toShow.getOrNull(1) == true) queries.add("""favoriteAnime: ${favMediaQuery(true, 1)}""")
|
||||
if (toShow.getOrNull(2) == true) queries.add(
|
||||
"""plannedAnime: ${
|
||||
continueMediaQuery(
|
||||
"ANIME",
|
||||
"PLANNING"
|
||||
)
|
||||
}"""
|
||||
)
|
||||
if (toShow.getOrNull(3) == true) {
|
||||
queries.add("""currentManga: ${continueMediaQuery("MANGA", "CURRENT")}""")
|
||||
queries.add("""repeatingManga: ${continueMediaQuery("MANGA", "REPEATING")}""")
|
||||
}
|
||||
if (toShow.getOrNull(4) == true) queries.add(
|
||||
"""favoriteManga: ${
|
||||
favMediaQuery(
|
||||
false,
|
||||
1
|
||||
)
|
||||
}"""
|
||||
)
|
||||
if (toShow.getOrNull(5) == true) queries.add(
|
||||
"""plannedManga: ${
|
||||
continueMediaQuery(
|
||||
"MANGA",
|
||||
"PLANNING"
|
||||
)
|
||||
}"""
|
||||
)
|
||||
if (toShow.getOrNull(6) == true) {
|
||||
queries.add("""recommendationQuery: ${recommendationQuery()}""")
|
||||
queries.add("""recommendationPlannedQueryAnime: ${recommendationPlannedQuery("ANIME")}""")
|
||||
queries.add("""recommendationPlannedQueryManga: ${recommendationPlannedQuery("MANGA")}""")
|
||||
}
|
||||
|
||||
val query = "{${queries.joinToString(",")}}"
|
||||
val response = executeQuery<Query.HomePageMedia>(query, show = true)
|
||||
val returnMap = mutableMapOf<String, ArrayList<*>>()
|
||||
fun current(type: String) {
|
||||
val returnMap = mutableMapOf<String, ArrayList<Media>>()
|
||||
|
||||
fun processMedia(
|
||||
type: String,
|
||||
currentMedia: List<MediaList>?,
|
||||
repeatingMedia: List<MediaList>?
|
||||
) {
|
||||
val subMap = mutableMapOf<Int, Media>()
|
||||
val returnArray = arrayListOf<Media>()
|
||||
val current =
|
||||
if (type == "Anime") response?.data?.currentAnime else response?.data?.currentManga
|
||||
val repeating =
|
||||
if (type == "Anime") response?.data?.repeatingAnime else response?.data?.repeatingManga
|
||||
current?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
removedMedia.add(m)
|
||||
}
|
||||
|
||||
(currentMedia ?: emptyList()).forEach { entry ->
|
||||
val media = Media(entry)
|
||||
if (media.id !in removeList && (!hidePrivate || !media.isListPrivate)) {
|
||||
media.cameFromContinue = true
|
||||
subMap[media.id] = media
|
||||
} else {
|
||||
removedMedia.add(media)
|
||||
}
|
||||
}
|
||||
|
||||
repeating?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
removedMedia.add(m)
|
||||
}
|
||||
(repeatingMedia ?: emptyList()).forEach { entry ->
|
||||
val media = Media(entry)
|
||||
if (media.id !in removeList && (!hidePrivate || !media.isListPrivate)) {
|
||||
media.cameFromContinue = true
|
||||
subMap[media.id] = media
|
||||
} else {
|
||||
removedMedia.add(media)
|
||||
}
|
||||
}
|
||||
if (type != "Anime") {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continue${type}List",
|
||||
listOf<Int>(),
|
||||
List::class.java
|
||||
) as List<Int>
|
||||
if (list.isNotEmpty()) {
|
||||
list.reversed().forEach { id ->
|
||||
subMap[id]?.let { returnArray.add(it) }
|
||||
}
|
||||
subMap.values.forEach {
|
||||
if (!returnArray.contains(it)) returnArray.add(it)
|
||||
}
|
||||
} else {
|
||||
returnArray.addAll(subMap.values)
|
||||
returnMap["current$type"] = returnArray
|
||||
return
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
List::class.java
|
||||
) as List<Int>
|
||||
if (list.isNotEmpty()) {
|
||||
list.reversed().forEach {
|
||||
if (subMap.containsKey(it)) returnArray.add(subMap[it]!!)
|
||||
}
|
||||
for (i in subMap) {
|
||||
if (i.value !in returnArray) returnArray.add(i.value)
|
||||
}
|
||||
} else returnArray.addAll(subMap.values)
|
||||
returnMap["current$type"] = returnArray
|
||||
|
||||
}
|
||||
|
||||
fun planned(type: String) {
|
||||
val subMap = mutableMapOf<Int, Media>()
|
||||
val returnArray = arrayListOf<Media>()
|
||||
val current =
|
||||
if (type == "Anime") response?.data?.plannedAnime else response?.data?.plannedManga
|
||||
current?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
removedMedia.add(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val list = PrefManager.getNullableCustomVal(
|
||||
"continueAnimeList",
|
||||
listOf<Int>(),
|
||||
List::class.java
|
||||
) as List<Int>
|
||||
if (list.isNotEmpty()) {
|
||||
list.reversed().forEach {
|
||||
if (subMap.containsKey(it)) returnArray.add(subMap[it]!!)
|
||||
}
|
||||
for (i in subMap) {
|
||||
if (i.value !in returnArray) returnArray.add(i.value)
|
||||
}
|
||||
} else returnArray.addAll(subMap.values)
|
||||
returnMap["planned$type"] = returnArray
|
||||
}
|
||||
if (toShow.getOrNull(0) == true) processMedia(
|
||||
"Anime",
|
||||
response?.data?.currentAnime?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(),
|
||||
response?.data?.repeatingAnime?.lists?.flatMap { it.entries ?: emptyList() }?.reversed()
|
||||
)
|
||||
if (toShow.getOrNull(2) == true) processMedia(
|
||||
"AnimePlanned",
|
||||
response?.data?.plannedAnime?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(),
|
||||
null
|
||||
)
|
||||
if (toShow.getOrNull(3) == true) processMedia(
|
||||
"Manga",
|
||||
response?.data?.currentManga?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(),
|
||||
response?.data?.repeatingManga?.lists?.flatMap { it.entries ?: emptyList() }?.reversed()
|
||||
)
|
||||
if (toShow.getOrNull(5) == true) processMedia(
|
||||
"MangaPlanned",
|
||||
response?.data?.plannedManga?.lists?.flatMap { it.entries ?: emptyList() }?.reversed(),
|
||||
null
|
||||
)
|
||||
|
||||
fun favorite(type: String) {
|
||||
val favourites =
|
||||
if (type == "Anime") response?.data?.favoriteAnime?.favourites else response?.data?.favoriteManga?.favourites
|
||||
val apiMediaList = if (type == "Anime") favourites?.anime else favourites?.manga
|
||||
fun processFavorites(type: String, favorites: List<MediaEdge>?) {
|
||||
val returnArray = arrayListOf<Media>()
|
||||
apiMediaList?.edges?.forEach {
|
||||
it.node?.let { i ->
|
||||
val m = Media(i).apply { isFav = true }
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
returnArray.add(m)
|
||||
favorites?.forEach { edge ->
|
||||
edge.node?.let {
|
||||
val media = Media(it).apply { isFav = true }
|
||||
if (media.id !in removeList && (!hidePrivate || !media.isListPrivate)) {
|
||||
returnArray.add(media)
|
||||
} else {
|
||||
removedMedia.add(m)
|
||||
removedMedia.add(media)
|
||||
}
|
||||
}
|
||||
}
|
||||
returnMap["favorite$type"] = returnArray
|
||||
}
|
||||
|
||||
if (toShow.getOrNull(0) == true) {
|
||||
current("Anime")
|
||||
}
|
||||
if (toShow.getOrNull(1) == true) {
|
||||
favorite("Anime")
|
||||
}
|
||||
if (toShow.getOrNull(2) == true) {
|
||||
planned("Anime")
|
||||
}
|
||||
if (toShow.getOrNull(3) == true) {
|
||||
current("Manga")
|
||||
}
|
||||
if (toShow.getOrNull(4) == true) {
|
||||
favorite("Manga")
|
||||
}
|
||||
if (toShow.getOrNull(5) == true) {
|
||||
planned("Manga")
|
||||
}
|
||||
if (toShow.getOrNull(1) == true) processFavorites(
|
||||
"Anime",
|
||||
response?.data?.favoriteAnime?.favourites?.anime?.edges
|
||||
)
|
||||
if (toShow.getOrNull(4) == true) processFavorites(
|
||||
"Manga",
|
||||
response?.data?.favoriteManga?.favourites?.manga?.edges
|
||||
)
|
||||
|
||||
if (toShow.getOrNull(6) == true) {
|
||||
val subMap = mutableMapOf<Int, Media>()
|
||||
response?.data?.recommendationQuery?.apply {
|
||||
recommendations?.onEach {
|
||||
val json = it.mediaRecommendation
|
||||
if (json != null) {
|
||||
val m = Media(json)
|
||||
m.relation = json.type?.toString()
|
||||
subMap[m.id] = m
|
||||
}
|
||||
response?.data?.recommendationQuery?.recommendations?.forEach {
|
||||
it.mediaRecommendation?.let { json ->
|
||||
val media = Media(json)
|
||||
media.relation = json.type?.toString()
|
||||
subMap[media.id] = media
|
||||
}
|
||||
}
|
||||
response?.data?.recommendationPlannedQueryAnime?.apply {
|
||||
lists?.forEach { li ->
|
||||
li.entries?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.status == "RELEASING" || m.status == "FINISHED") {
|
||||
m.relation = it.media?.type?.toString()
|
||||
subMap[m.id] = m
|
||||
}
|
||||
}
|
||||
response?.data?.recommendationPlannedQueryAnime?.lists?.flatMap {
|
||||
it.entries ?: emptyList()
|
||||
}?.forEach {
|
||||
val media = Media(it)
|
||||
if (media.status in listOf("RELEASING", "FINISHED")) {
|
||||
media.relation = it.media?.type?.toString()
|
||||
subMap[media.id] = media
|
||||
}
|
||||
}
|
||||
response?.data?.recommendationPlannedQueryManga?.apply {
|
||||
lists?.forEach { li ->
|
||||
li.entries?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.status == "RELEASING" || m.status == "FINISHED") {
|
||||
m.relation = it.media?.type?.toString()
|
||||
subMap[m.id] = m
|
||||
}
|
||||
}
|
||||
response?.data?.recommendationPlannedQueryManga?.lists?.flatMap {
|
||||
it.entries ?: emptyList()
|
||||
}?.forEach {
|
||||
val media = Media(it)
|
||||
if (media.status in listOf("RELEASING", "FINISHED")) {
|
||||
media.relation = it.media?.type?.toString()
|
||||
subMap[media.id] = media
|
||||
}
|
||||
}
|
||||
val list = ArrayList(subMap.values.toList())
|
||||
list.sortByDescending { it.meanScore }
|
||||
val list = ArrayList(subMap.values).apply { sortByDescending { it.meanScore } }
|
||||
returnMap["recommendations"] = list
|
||||
}
|
||||
|
||||
@@ -1061,102 +1031,97 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult:
|
||||
media1?.media?.mapTo(combinedList) { Media(it) }
|
||||
return combinedList
|
||||
}
|
||||
private fun getPreference(pref: PrefName): Boolean = PrefManager.getVal(pref)
|
||||
private fun buildQueryString(sort: String, type: String, format: String? = null, country: String? = null): String {
|
||||
val includeList = if (type == "ANIME" && !getPreference(PrefName.IncludeAnimeList)) "onList:false" else if (type == "MANGA" && !getPreference(PrefName.IncludeMangaList)) "onList:false" else ""
|
||||
val isAdult = if (getPreference(PrefName.AdultOnly)) "isAdult:true" else ""
|
||||
val formatFilter = format?.let { "format: $it, " } ?: ""
|
||||
val countryFilter = country?.let { "countryOfOrigin: $it, " } ?: ""
|
||||
|
||||
return """Page(page:1,perPage:50){
|
||||
pageInfo{hasNextPage total}
|
||||
media(sort:$sort, type:$type, $formatFilter $countryFilter $includeList $isAdult){
|
||||
id idMal status chapters episodes nextAiringEpisode{episode}
|
||||
isAdult type meanScore isFavourite format bannerImage countryOfOrigin
|
||||
coverImage{large} title{english romaji userPreferred}
|
||||
mediaListEntry{progress private score(format:POINT_100) status}
|
||||
private fun getPreference(pref: PrefName): Boolean = PrefManager.getVal(pref)
|
||||
|
||||
private fun buildQueryString(
|
||||
sort: String,
|
||||
type: String,
|
||||
format: String? = null,
|
||||
country: String? = null
|
||||
): String {
|
||||
val includeList = when {
|
||||
type == "ANIME" && !getPreference(PrefName.IncludeAnimeList) -> "onList:false"
|
||||
type == "MANGA" && !getPreference(PrefName.IncludeMangaList) -> "onList:false"
|
||||
else -> ""
|
||||
}
|
||||
val isAdult = if (getPreference(PrefName.AdultOnly)) "isAdult:true" else ""
|
||||
val formatFilter = format?.let { "format:$it, " } ?: ""
|
||||
val countryFilter = country?.let { "countryOfOrigin:$it, " } ?: ""
|
||||
|
||||
return buildString {
|
||||
append("""Page(page:1,perPage:50){pageInfo{hasNextPage total}media(sort:$sort, type:$type, $formatFilter $countryFilter $includeList $isAdult){id idMal status chapters episodes nextAiringEpisode{episode} isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large} title{english romaji userPreferred} mediaListEntry{progress private score(format:POINT_100) status}}}""")
|
||||
}
|
||||
}"""
|
||||
}
|
||||
|
||||
private fun recentAnimeUpdates(page: Int): String {
|
||||
val currentTime = System.currentTimeMillis() / 1000
|
||||
return """Page(page:$page,perPage:50){
|
||||
pageInfo{hasNextPage total}
|
||||
airingSchedules(airingAt_greater:0 airingAt_lesser:${currentTime - 10000} sort:TIME_DESC){
|
||||
episode airingAt media{
|
||||
id idMal status chapters episodes nextAiringEpisode{episode}
|
||||
isAdult type meanScore isFavourite format bannerImage countryOfOrigin
|
||||
coverImage{large} title{english romaji userPreferred}
|
||||
mediaListEntry{progress private score(format:POINT_100) status}
|
||||
}
|
||||
return buildString {
|
||||
append("""Page(page:$page,perPage:50){pageInfo{hasNextPage total}airingSchedules(airingAt_greater:0 airingAt_lesser:${currentTime - 10000} sort:TIME_DESC){episode airingAt media{id idMal status chapters episodes nextAiringEpisode{episode} isAdult type meanScore isFavourite format bannerImage countryOfOrigin coverImage{large} title{english romaji userPreferred} mediaListEntry{progress private score(format:POINT_100) status}}}}""")
|
||||
}
|
||||
}"""
|
||||
}
|
||||
private fun queryAnimeList(): String {
|
||||
return """{
|
||||
recentUpdates:${recentAnimeUpdates(1)}
|
||||
recentUpdates2:${recentAnimeUpdates(2)}
|
||||
trendingMovies:${buildQueryString("POPULARITY_DESC", "ANIME", "MOVIE")}
|
||||
topRated:${buildQueryString("SCORE_DESC", "ANIME")}
|
||||
mostFav:${buildQueryString("FAVOURITES_DESC", "ANIME")}
|
||||
}"""
|
||||
}
|
||||
private fun queryMangaList(): String {
|
||||
return """{
|
||||
trendingManga:${buildQueryString("POPULARITY_DESC", "MANGA", country = "JP")}
|
||||
trendingManhwa:${buildQueryString("POPULARITY_DESC", "MANGA", country = "KR")}
|
||||
trendingNovel:${buildQueryString("POPULARITY_DESC", "MANGA", format = "NOVEL", country = "JP")}
|
||||
topRated:${buildQueryString("SCORE_DESC", "MANGA")}
|
||||
mostFav:${buildQueryString("FAVOURITES_DESC", "MANGA")}
|
||||
|
||||
}"""
|
||||
}
|
||||
|
||||
suspend fun loadAnimeList(): Map<String, ArrayList<Media>> {
|
||||
private fun queryAnimeList(): String {
|
||||
return buildString {
|
||||
append("""{recentUpdates:${recentAnimeUpdates(1)} recentUpdates2:${recentAnimeUpdates(2)} trendingMovies:${buildQueryString("POPULARITY_DESC", "ANIME", "MOVIE")} topRated:${buildQueryString("SCORE_DESC", "ANIME")} mostFav:${buildQueryString("FAVOURITES_DESC", "ANIME")}}""")
|
||||
}
|
||||
}
|
||||
|
||||
private fun queryMangaList(): String {
|
||||
return buildString {
|
||||
append("""{trendingManga:${buildQueryString("POPULARITY_DESC", "MANGA", country = "JP")} trendingManhwa:${buildQueryString("POPULARITY_DESC", "MANGA", country = "KR")} trendingNovel:${buildQueryString("POPULARITY_DESC", "MANGA", format = "NOVEL", country = "JP")} topRated:${buildQueryString("SCORE_DESC", "MANGA")} mostFav:${buildQueryString("FAVOURITES_DESC", "MANGA")}}""")
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadAnimeList(): Map<String, ArrayList<Media>> = coroutineScope {
|
||||
val list = mutableMapOf<String, ArrayList<Media>>()
|
||||
|
||||
fun filterRecentUpdates(
|
||||
page: Page?,
|
||||
): ArrayList<Media> {
|
||||
val listOnly: Boolean = PrefManager.getVal(PrefName.RecentlyListOnly)
|
||||
val adultOnly: Boolean = PrefManager.getVal(PrefName.AdultOnly)
|
||||
val idArr = mutableListOf<Int>()
|
||||
fun filterRecentUpdates(page: Page?): ArrayList<Media> {
|
||||
val listOnly = getPreference(PrefName.RecentlyListOnly)
|
||||
val adultOnly = getPreference(PrefName.AdultOnly)
|
||||
val idArr = mutableSetOf<Int>()
|
||||
return page?.airingSchedules?.mapNotNull { i ->
|
||||
i.media?.let {
|
||||
if (!idArr.contains(it.id)) {
|
||||
val shouldAdd = when {
|
||||
!listOnly && it.countryOfOrigin == "JP" && Anilist.adult && adultOnly && it.isAdult == true -> true
|
||||
!listOnly && !adultOnly && it.countryOfOrigin == "JP" && it.isAdult == false -> true
|
||||
listOnly && it.mediaListEntry != null -> true
|
||||
else -> false
|
||||
}
|
||||
if (shouldAdd) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else null
|
||||
i.media?.takeIf { !idArr.contains(it.id) }?.let {
|
||||
val shouldAdd = when {
|
||||
!listOnly && it.countryOfOrigin == "JP" && adultOnly && it.isAdult == true -> true
|
||||
!listOnly && !adultOnly && it.countryOfOrigin == "JP" && it.isAdult == false -> true
|
||||
listOnly && it.mediaListEntry != null -> true
|
||||
else -> false
|
||||
}
|
||||
if (shouldAdd) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else null
|
||||
}
|
||||
}?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
}
|
||||
executeQuery<Query.AnimeList>(queryAnimeList(), force = true)?.data?.apply {
|
||||
|
||||
val animeList = async { executeQuery<Query.AnimeList>(queryAnimeList(), force = true) }
|
||||
|
||||
animeList.await()?.data?.apply {
|
||||
list["recentUpdates"] = filterRecentUpdates(recentUpdates)
|
||||
list["trendingMovies"] = mediaList(trendingMovies)
|
||||
list["topRated"] = mediaList(topRated)
|
||||
list["mostFav"] = mediaList(mostFav)
|
||||
}
|
||||
return list
|
||||
|
||||
list
|
||||
}
|
||||
suspend fun loadMangaList(): Map<String, ArrayList<Media>> {
|
||||
|
||||
suspend fun loadMangaList(): Map<String, ArrayList<Media>> = coroutineScope {
|
||||
val list = mutableMapOf<String, ArrayList<Media>>()
|
||||
executeQuery<Query.MangaList>(queryMangaList(), force = true)?.data?.apply {
|
||||
|
||||
val mangaList = async { executeQuery<Query.MangaList>(queryMangaList(), force = true) }
|
||||
|
||||
mangaList.await()?.data?.apply {
|
||||
list["trendingManga"] = mediaList(trendingManga)
|
||||
list["trendingManhwa"] = mediaList(trendingManhwa)
|
||||
list["trendingNovel"] = mediaList(trendingNovel)
|
||||
list["topRated"] = mediaList(topRated)
|
||||
list["mostFav"] = mediaList(mostFav)
|
||||
}
|
||||
return list
|
||||
|
||||
list
|
||||
}
|
||||
|
||||
|
||||
@@ -1560,10 +1525,10 @@ Page(page:$page,perPage:50) {
|
||||
resetNotification: Boolean = true,
|
||||
type: Boolean? = null
|
||||
): NotificationResponse? {
|
||||
val type_in = "type_in:[AIRING,MEDIA_MERGE,MEDIA_DELETION,MEDIA_DATA_CHANGE]"
|
||||
val typeIn = "type_in:[AIRING,MEDIA_MERGE,MEDIA_DELETION,MEDIA_DATA_CHANGE]"
|
||||
val reset = if (resetNotification) "true" else "false"
|
||||
val res = executeQuery<NotificationResponse>(
|
||||
"""{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){pageInfo{currentPage,hasNextPage}notifications(resetNotificationCount:$reset , ${if (type == true) type_in else ""}){__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,}}}}""",
|
||||
"""{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){pageInfo{currentPage,hasNextPage}notifications(resetNotificationCount:$reset , ${if (type == true) typeIn else ""}){__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 && resetNotification) {
|
||||
|
||||
@@ -91,17 +91,16 @@ class AnilistHomeViewModel : ViewModel() {
|
||||
|
||||
fun getHidden(): LiveData<ArrayList<Media>> = hidden
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
suspend fun initHomePage() {
|
||||
val res = Anilist.query.initHomePage()
|
||||
res["currentAnime"]?.let { animeContinue.postValue(it as ArrayList<Media>?) }
|
||||
res["favoriteAnime"]?.let { animeFav.postValue(it as ArrayList<Media>?) }
|
||||
res["plannedAnime"]?.let { animePlanned.postValue(it as ArrayList<Media>?) }
|
||||
res["currentManga"]?.let { mangaContinue.postValue(it as ArrayList<Media>?) }
|
||||
res["favoriteManga"]?.let { mangaFav.postValue(it as ArrayList<Media>?) }
|
||||
res["plannedManga"]?.let { mangaPlanned.postValue(it as ArrayList<Media>?) }
|
||||
res["recommendations"]?.let { recommendation.postValue(it as ArrayList<Media>?) }
|
||||
res["hidden"]?.let { hidden.postValue(it as ArrayList<Media>?) }
|
||||
res["currentAnime"]?.let { animeContinue.postValue(it) }
|
||||
res["favoriteAnime"]?.let { animeFav.postValue(it) }
|
||||
res["currentAnimePlanned"]?.let { animePlanned.postValue(it) }
|
||||
res["currentManga"]?.let { mangaContinue.postValue(it) }
|
||||
res["favoriteManga"]?.let { mangaFav.postValue(it) }
|
||||
res["currentMangaPlanned"]?.let { mangaPlanned.postValue(it) }
|
||||
res["recommendations"]?.let { recommendation.postValue(it) }
|
||||
res["hidden"]?.let { hidden.postValue(it) }
|
||||
}
|
||||
|
||||
suspend fun loadMain(context: FragmentActivity) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_STAR
|
||||
import ani.dantotsu.media.manga.MangaReadFragment.Companion.EXTRA_CHAPTER_NUMBER
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.NumberConverter.Companion.ofLength
|
||||
import com.anggrayudi.storage.file.deleteRecursively
|
||||
import com.anggrayudi.storage.file.forceDelete
|
||||
import com.anggrayudi.storage.file.openOutputStream
|
||||
@@ -235,7 +236,7 @@ class MangaDownloaderService : Service() {
|
||||
}
|
||||
|
||||
if (bitmap != null) {
|
||||
saveToDisk("$index.jpg", outputDir, bitmap)
|
||||
saveToDisk("${index.ofLength(3)}.jpg", outputDir, bitmap)
|
||||
}
|
||||
farthest++
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.util.Logger
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.math.max
|
||||
@@ -457,53 +458,56 @@ class HomeFragment : Fragment() {
|
||||
|
||||
var running = false
|
||||
val live = Refresh.activity.getOrPut(1) { MutableLiveData(true) }
|
||||
live.observe(viewLifecycleOwner)
|
||||
{
|
||||
if (!running && it) {
|
||||
live.observe(viewLifecycleOwner) { shouldRefresh ->
|
||||
if (!running && shouldRefresh) {
|
||||
running = true
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
//Get userData First
|
||||
Anilist.userid =
|
||||
PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)
|
||||
?.toIntOrNull()
|
||||
// Get user data first
|
||||
Anilist.userid = PrefManager.getNullableVal<String>(PrefName.AnilistUserId, null)?.toIntOrNull()
|
||||
if (Anilist.userid == null) {
|
||||
getUserId(requireContext()) {
|
||||
load()
|
||||
}
|
||||
} else {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
getUserId(requireContext()) {
|
||||
load()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getUserId(requireContext()) {
|
||||
load()
|
||||
}
|
||||
}
|
||||
model.loaded = true
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
model.setListImages()
|
||||
}
|
||||
model.setListImages()
|
||||
}
|
||||
|
||||
var empty = true
|
||||
val homeLayoutShow: List<Boolean> =
|
||||
PrefManager.getVal(PrefName.HomeLayout)
|
||||
model.initHomePage()
|
||||
model.initUserStatus()
|
||||
(array.indices).forEach { i ->
|
||||
var empty = true
|
||||
val homeLayoutShow: List<Boolean> = PrefManager.getVal(PrefName.HomeLayout)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
homeLayoutShow.indices.forEach { i ->
|
||||
if (homeLayoutShow.elementAt(i)) {
|
||||
empty = false
|
||||
} else withContext(Dispatchers.Main) {
|
||||
} else {
|
||||
containers[i].visibility = View.GONE
|
||||
}
|
||||
}
|
||||
model.empty.postValue(empty)
|
||||
}
|
||||
|
||||
val initHomePage = async(Dispatchers.IO) { model.initHomePage() }
|
||||
val initUserStatus = async(Dispatchers.IO) { model.initUserStatus() }
|
||||
initHomePage.await()
|
||||
initUserStatus.await()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
model.empty.postValue(empty)
|
||||
binding.homeHiddenItemsContainer.visibility = View.GONE
|
||||
}
|
||||
|
||||
live.postValue(false)
|
||||
_binding?.homeRefresh?.isRefreshing = false
|
||||
running = false
|
||||
}
|
||||
binding.homeHiddenItemsContainer.visibility = View.GONE
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,10 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||
if (activity.getOrNull(position) != null) {
|
||||
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
|
||||
val startIndex = if ( startFrom > 0) startFrom else 0
|
||||
binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1)
|
||||
binding.stories.setStoriesList(
|
||||
activityList = activity[position].activity,
|
||||
startIndex = startIndex + 1
|
||||
)
|
||||
} else {
|
||||
Logger.log("index out of bounds for position $position of size ${activity.size}")
|
||||
finish()
|
||||
@@ -92,7 +95,7 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
|
||||
val startIndex= if ( startFrom > 0) startFrom else 0
|
||||
binding.stories.startAnimation(slideOutLeft)
|
||||
binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1)
|
||||
binding.stories.setStoriesList(activity[position].activity, startIndex + 1)
|
||||
binding.stories.startAnimation(slideInRight)
|
||||
} else {
|
||||
finish()
|
||||
@@ -107,7 +110,7 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
|
||||
val startIndex = if ( startFrom > 0) startFrom else 0
|
||||
binding.stories.startAnimation(slideOutRight)
|
||||
binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1)
|
||||
binding.stories.setStoriesList(activity[position].activity,startIndex + 1)
|
||||
binding.stories.startAnimation(slideInLeft)
|
||||
} else {
|
||||
finish()
|
||||
|
||||
@@ -49,7 +49,6 @@ import kotlin.math.abs
|
||||
class Stories @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), View.OnTouchListener {
|
||||
private lateinit var activity: FragmentActivity
|
||||
private lateinit var binding: FragmentStatusBinding
|
||||
private lateinit var activityList: List<Activity>
|
||||
private lateinit var storiesListener: StoriesCallback
|
||||
@@ -80,10 +79,9 @@ class Stories @JvmOverloads constructor(
|
||||
|
||||
|
||||
fun setStoriesList(
|
||||
activityList: List<Activity>, activity: FragmentActivity, startIndex: Int = 1
|
||||
activityList: List<Activity>, startIndex: Int = 1
|
||||
) {
|
||||
this.activityList = activityList
|
||||
this.activity = activity
|
||||
this.storyIndex = startIndex
|
||||
addLoadingViews(activityList)
|
||||
}
|
||||
@@ -368,7 +366,9 @@ class Stories @JvmOverloads constructor(
|
||||
if (
|
||||
story.status?.contains("completed") == false &&
|
||||
!story.status.contains("plans") &&
|
||||
!story.status.contains("repeating")
|
||||
!story.status.contains("repeating")&&
|
||||
!story.status.contains("paused")&&
|
||||
!story.status.contains("dropped")
|
||||
) {
|
||||
"of ${story.media?.title?.userPreferred}"
|
||||
} else {
|
||||
@@ -389,7 +389,7 @@ class Stories @JvmOverloads constructor(
|
||||
story.media?.id
|
||||
),
|
||||
ActivityOptionsCompat.makeSceneTransitionAnimation(
|
||||
activity,
|
||||
(it.context as FragmentActivity),
|
||||
binding.coverImage,
|
||||
ViewCompat.getTransitionName(binding.coverImage)!!
|
||||
).toBundle()
|
||||
@@ -427,7 +427,7 @@ class Stories @JvmOverloads constructor(
|
||||
binding.activityReplies.setColorFilter(ContextCompat.getColor(context, R.color.bg_opp))
|
||||
binding.activityRepliesContainer.setOnClickListener {
|
||||
RepliesBottomDialog.newInstance(story.id)
|
||||
.show(activity.supportFragmentManager, "replies")
|
||||
.show((it.context as FragmentActivity).supportFragmentManager, "replies")
|
||||
}
|
||||
binding.activityLike.setColorFilter(if (story.isLiked == true) likeColor else notLikeColor)
|
||||
binding.activityLikeCount.text = story.likeCount.toString()
|
||||
@@ -435,10 +435,9 @@ class Stories @JvmOverloads constructor(
|
||||
like()
|
||||
}
|
||||
binding.activityLikeContainer.setOnLongClickListener {
|
||||
val context = activity
|
||||
UsersDialogFragment().apply {
|
||||
userList(userList)
|
||||
show(context.supportFragmentManager, "dialog")
|
||||
show((it.context as FragmentActivity).supportFragmentManager, "dialog")
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class ActivityFragment : Fragment() {
|
||||
binding.feedRefresh.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
bottomMargin = navBarHeight
|
||||
}
|
||||
binding.emptyTextView.text = getString(R.string.no_activities)
|
||||
binding.emptyTextView.text = getString(R.string.nothing_here)
|
||||
lifecycleScope.launch {
|
||||
getList()
|
||||
if (adapter.itemCount == 0) {
|
||||
|
||||
@@ -51,6 +51,7 @@ class FeedActivity : AppCompatActivity() {
|
||||
binding.notificationBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
|
||||
val getOne = intent.getIntExtra("activityId", -1)
|
||||
if (getOne != -1) { navBar.visibility = View.GONE }
|
||||
binding.notificationViewPager.isUserInputEnabled = false
|
||||
binding.notificationViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
|
||||
binding.notificationViewPager.setOffscreenPageLimit(4)
|
||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||
@@ -63,13 +64,7 @@ class FeedActivity : AppCompatActivity() {
|
||||
newTab: AnimatedBottomBar.Tab
|
||||
) {
|
||||
selected = newIndex
|
||||
binding.notificationViewPager.setCurrentItem(selected, true)
|
||||
}
|
||||
})
|
||||
binding.notificationViewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
navBar.selectTabAt(position)
|
||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.*
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.newInstance
|
||||
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||
|
||||
class NotificationActivity : AppCompatActivity() {
|
||||
@@ -48,6 +49,7 @@ class NotificationActivity : AppCompatActivity() {
|
||||
binding.notificationBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
|
||||
val getOne = intent.getIntExtra("activityId", -1)
|
||||
if (getOne != -1) navBar.isVisible = false
|
||||
binding.notificationViewPager.isUserInputEnabled = false
|
||||
binding.notificationViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
|
||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||
navBar.selectTabAt(selected)
|
||||
@@ -59,13 +61,7 @@ class NotificationActivity : AppCompatActivity() {
|
||||
newTab: AnimatedBottomBar.Tab
|
||||
) {
|
||||
selected = newIndex
|
||||
binding.notificationViewPager.setCurrentItem(selected, true)
|
||||
}
|
||||
})
|
||||
binding.notificationViewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
navBar.selectTabAt(position)
|
||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -83,11 +79,11 @@ class NotificationActivity : AppCompatActivity() {
|
||||
override fun getItemCount(): Int = if (id != -1) 1 else 4
|
||||
|
||||
override fun createFragment(position: Int): Fragment = when (position) {
|
||||
0 -> NotificationFragment.newInstance(NotificationType.USER)
|
||||
1 -> NotificationFragment.newInstance(if (id != -1) NotificationType.ONE else NotificationType.MEDIA, id)
|
||||
2 -> NotificationFragment.newInstance(NotificationType.SUBSCRIPTION)
|
||||
3 -> NotificationFragment.newInstance(NotificationType.COMMENT)
|
||||
else -> NotificationFragment.newInstance(NotificationType.MEDIA)
|
||||
0 -> newInstance(USER)
|
||||
1 -> newInstance(if (id != -1) ONE else MEDIA, id)
|
||||
2 -> newInstance(SUBSCRIPTION)
|
||||
3 -> newInstance(COMMENT)
|
||||
else -> newInstance(MEDIA)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ import ani.dantotsu.notifications.comment.CommentStore
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionStore
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.profile.activity.FeedActivity
|
||||
import ani.dantotsu.setBaseline
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.COMMENT
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.MEDIA
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.ONE
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.SUBSCRIPTION
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.USER
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
@@ -29,8 +33,8 @@ import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class NotificationFragment : Fragment() {
|
||||
private lateinit var type : NotificationType
|
||||
private var getID : Int = -1
|
||||
private lateinit var type: NotificationType
|
||||
private var getID: Int = -1
|
||||
private lateinit var binding: FragmentNotificationsBinding
|
||||
private var adapter: GroupieAdapter = GroupieAdapter()
|
||||
private var currentPage = 1
|
||||
@@ -53,12 +57,10 @@ class NotificationFragment : Fragment() {
|
||||
binding.notificationRecyclerView.adapter = adapter
|
||||
binding.notificationRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
binding.notificationProgressBar.isVisible = true
|
||||
binding.emptyTextView.text = getString(R.string.no_notifications)
|
||||
binding.emptyTextView.text = getString(R.string.nothing_here)
|
||||
lifecycleScope.launch {
|
||||
getList()
|
||||
if (adapter.itemCount == 0) {
|
||||
binding.emptyTextView.isVisible = true
|
||||
}
|
||||
|
||||
binding.notificationProgressBar.isVisible = false
|
||||
}
|
||||
binding.notificationSwipeRefresh.setOnRefreshListener {
|
||||
@@ -87,13 +89,16 @@ class NotificationFragment : Fragment() {
|
||||
|
||||
private suspend fun getList() {
|
||||
val list = when (type) {
|
||||
NotificationType.ONE -> getNotificationsFiltered(false) { it.id == getID }
|
||||
NotificationType.MEDIA -> getNotificationsFiltered(type = true) { it.media != null }
|
||||
NotificationType.USER -> getNotificationsFiltered { it.media == null }
|
||||
NotificationType.SUBSCRIPTION -> getSubscriptions()
|
||||
NotificationType.COMMENT -> getComments()
|
||||
ONE -> getNotificationsFiltered(false) { it.id == getID }
|
||||
MEDIA -> getNotificationsFiltered(type = true) { it.media != null }
|
||||
USER -> getNotificationsFiltered { it.media == null }
|
||||
SUBSCRIPTION -> getSubscriptions()
|
||||
COMMENT -> getComments()
|
||||
}
|
||||
adapter.addAll(list.map { NotificationItem(it, type, adapter, ::onClick) })
|
||||
if (adapter.itemCount == 0) {
|
||||
binding.emptyTextView.isVisible = true
|
||||
}
|
||||
adapter.addAll(list.map { NotificationItem(it, ::onClick) })
|
||||
}
|
||||
|
||||
private suspend fun getNotificationsFiltered(
|
||||
@@ -114,8 +119,11 @@ class NotificationFragment : Fragment() {
|
||||
PrefName.SubscriptionNotificationStore,
|
||||
null
|
||||
) ?: listOf()
|
||||
return list.sortedByDescending { (it.time / 1000L).toInt() }
|
||||
.filter { it.image != null }.map {
|
||||
|
||||
return list
|
||||
.sortedByDescending { (it.time / 1000L).toInt() }
|
||||
.filter { it.image != null } // to remove old data
|
||||
.map {
|
||||
Notification(
|
||||
it.type,
|
||||
System.currentTimeMillis().toInt(),
|
||||
@@ -162,19 +170,31 @@ class NotificationFragment : Fragment() {
|
||||
|
||||
fun onClick(id: Int, optional: Int?, type: NotificationClickType) {
|
||||
val intent = when (type) {
|
||||
NotificationClickType.USER -> Intent(requireContext(), ProfileActivity::class.java).apply {
|
||||
NotificationClickType.USER -> Intent(
|
||||
requireContext(),
|
||||
ProfileActivity::class.java
|
||||
).apply {
|
||||
putExtra("userId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.MEDIA -> Intent(requireContext(), MediaDetailsActivity::class.java).apply {
|
||||
NotificationClickType.MEDIA -> Intent(
|
||||
requireContext(),
|
||||
MediaDetailsActivity::class.java
|
||||
).apply {
|
||||
putExtra("mediaId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.ACTIVITY -> Intent(requireContext(), FeedActivity::class.java).apply {
|
||||
NotificationClickType.ACTIVITY -> Intent(
|
||||
requireContext(),
|
||||
FeedActivity::class.java
|
||||
).apply {
|
||||
putExtra("activityId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.COMMENT -> Intent(requireContext(), MediaDetailsActivity::class.java).apply {
|
||||
NotificationClickType.COMMENT -> Intent(
|
||||
requireContext(),
|
||||
MediaDetailsActivity::class.java
|
||||
).apply {
|
||||
putExtra("FRAGMENT_TO_LOAD", "COMMENTS")
|
||||
putExtra("mediaId", id)
|
||||
putExtra("commentId", optional ?: -1)
|
||||
@@ -188,6 +208,7 @@ class NotificationFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (this::binding.isInitialized) {
|
||||
|
||||
@@ -8,16 +8,27 @@ import ani.dantotsu.connections.anilist.api.Notification
|
||||
import ani.dantotsu.connections.anilist.api.NotificationType
|
||||
import ani.dantotsu.databinding.ItemNotificationBinding
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationClickType
|
||||
import ani.dantotsu.notifications.comment.CommentStore
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionStore
|
||||
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationClickType
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.COMMENT
|
||||
import ani.dantotsu.profile.notification.NotificationFragment.Companion.NotificationType.SUBSCRIPTION
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.toPx
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
||||
class NotificationItem(
|
||||
private val notification: Notification,
|
||||
val clickCallback: (Int, Int?, NotificationClickType) -> Unit
|
||||
) : BindableItem<ItemNotificationBinding>() {
|
||||
val type: NotificationFragment.Companion.NotificationType,
|
||||
val parentAdapter: GroupieAdapter,
|
||||
val clickCallback: (Int, Int?, NotificationClickType) -> Unit,
|
||||
|
||||
) : BindableItem<ItemNotificationBinding>() {
|
||||
private lateinit var binding: ItemNotificationBinding
|
||||
override fun bind(viewBinding: ItemNotificationBinding, position: Int) {
|
||||
binding = viewBinding
|
||||
@@ -25,6 +36,48 @@ class NotificationItem(
|
||||
setBinding()
|
||||
}
|
||||
|
||||
fun dialog() {
|
||||
when (type) {
|
||||
COMMENT, SUBSCRIPTION -> {
|
||||
binding.root.context.customAlertDialog().apply {
|
||||
setTitle(R.string.delete)
|
||||
setMessage(ActivityItemBuilder.getContent(notification))
|
||||
setPosButton(R.string.yes) {
|
||||
when (type) {
|
||||
COMMENT -> {
|
||||
val list = PrefManager.getNullableVal<List<CommentStore>>(
|
||||
PrefName.CommentNotificationStore,
|
||||
null
|
||||
) ?: listOf()
|
||||
val newList = list.filter { it.commentId != notification.commentId }
|
||||
PrefManager.setVal(PrefName.CommentNotificationStore, newList)
|
||||
parentAdapter.remove(this@NotificationItem)
|
||||
|
||||
}
|
||||
|
||||
SUBSCRIPTION -> {
|
||||
val list = PrefManager.getNullableVal<List<SubscriptionStore>>(
|
||||
PrefName.SubscriptionNotificationStore,
|
||||
null
|
||||
) ?: listOf()
|
||||
val newList = list.filter { (it.time / 1000L).toInt() != notification.createdAt}
|
||||
PrefManager.setVal(PrefName.SubscriptionNotificationStore, newList)
|
||||
parentAdapter.remove(this@NotificationItem)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.no)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getLayout(): Int {
|
||||
return R.layout.item_notification
|
||||
}
|
||||
@@ -33,7 +86,11 @@ class NotificationItem(
|
||||
return ItemNotificationBinding.bind(view)
|
||||
}
|
||||
|
||||
private fun image(user: Boolean = false, commentNotification: Boolean = false, newRelease: Boolean = false) {
|
||||
private fun image(
|
||||
user: Boolean = false,
|
||||
commentNotification: Boolean = false,
|
||||
newRelease: Boolean = false
|
||||
) {
|
||||
|
||||
val cover = if (user) notification.user?.bannerImage
|
||||
?: notification.user?.avatar?.medium else notification.media?.bannerImage
|
||||
@@ -348,6 +405,14 @@ class NotificationItem(
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.notificationCoverUser.setOnLongClickListener {
|
||||
dialog()
|
||||
true
|
||||
}
|
||||
binding.notificationBannerImage.setOnLongClickListener {
|
||||
dialog()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,31 +9,25 @@ import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.Item
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
||||
class SubscriptionItem(
|
||||
val id: Int,
|
||||
private val media: SubscriptionHelper.Companion.SubscribeMedia,
|
||||
private val adapter: GroupieAdapter
|
||||
private val adapter: GroupieAdapter,
|
||||
private val onItemRemoved: (Int) -> Unit
|
||||
) : BindableItem<ItemSubscriptionBinding>() {
|
||||
private lateinit var binding: ItemSubscriptionBinding
|
||||
override fun bind(p0: ItemSubscriptionBinding, p1: Int) {
|
||||
val context = p0.root.context
|
||||
binding = p0
|
||||
val parserName = if (media.isAnime)
|
||||
SubscriptionHelper.getAnimeParser(media.id).name
|
||||
else
|
||||
SubscriptionHelper.getMangaParser(media.id).name
|
||||
val mediaName = media.name
|
||||
val showName = "$mediaName ($parserName)"
|
||||
binding.subscriptionName.text = showName
|
||||
|
||||
override fun bind(viewBinding: ItemSubscriptionBinding, position: Int) {
|
||||
binding = viewBinding
|
||||
val context = binding.root.context
|
||||
|
||||
binding.subscriptionName.text = media.name
|
||||
binding.root.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MediaDetailsActivity::class.java).putExtra(
|
||||
"mediaId", media.id
|
||||
),
|
||||
Intent(context, MediaDetailsActivity::class.java).putExtra("mediaId", media.id),
|
||||
null
|
||||
)
|
||||
}
|
||||
@@ -41,14 +35,11 @@ class SubscriptionItem(
|
||||
binding.deleteSubscription.setOnClickListener {
|
||||
SubscriptionHelper.deleteSubscription(id, true)
|
||||
adapter.remove(this)
|
||||
onItemRemoved(id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayout(): Int {
|
||||
return R.layout.item_subscription
|
||||
}
|
||||
override fun getLayout(): Int = R.layout.item_subscription
|
||||
|
||||
override fun initializeViewBinding(p0: View): ItemSubscriptionBinding {
|
||||
return ItemSubscriptionBinding.bind(p0)
|
||||
}
|
||||
override fun initializeViewBinding(view: View): ItemSubscriptionBinding = ItemSubscriptionBinding.bind(view)
|
||||
}
|
||||
113
app/src/main/java/ani/dantotsu/settings/SubscriptionSource.kt
Normal file
113
app/src/main/java/ani/dantotsu/settings/SubscriptionSource.kt
Normal file
@@ -0,0 +1,113 @@
|
||||
package ani.dantotsu.settings
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.ItemExtensionBinding
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
||||
class SubscriptionSource(
|
||||
private val parserName: String,
|
||||
private val subscriptions: MutableList<SubscriptionHelper.Companion.SubscribeMedia>,
|
||||
private val adapter: GroupieAdapter,
|
||||
private var parserIcon: Drawable? = null,
|
||||
private val onGroupRemoved: (SubscriptionSource) -> Unit
|
||||
) : BindableItem<ItemExtensionBinding>() {
|
||||
private lateinit var binding: ItemExtensionBinding
|
||||
private var isExpanded = false
|
||||
|
||||
override fun bind(viewBinding: ItemExtensionBinding, position: Int) {
|
||||
binding = viewBinding
|
||||
binding.extensionNameTextView.text = parserName
|
||||
updateSubscriptionCount()
|
||||
binding.extensionSubscriptions.visibility = View.VISIBLE
|
||||
|
||||
binding.extensionSubscriptions.setOnClickListener(null)
|
||||
binding.root.setOnClickListener {
|
||||
isExpanded = !isExpanded
|
||||
toggleSubscriptions()
|
||||
}
|
||||
binding.subscriptionCount.setOnClickListener {
|
||||
showRemoveAllSubscriptionsDialog(it.context)
|
||||
}
|
||||
binding.extensionIconImageView.visibility = View.VISIBLE
|
||||
val layoutParams = binding.extensionIconImageView.layoutParams as ViewGroup.MarginLayoutParams
|
||||
layoutParams.leftMargin = 28
|
||||
binding.extensionIconImageView.layoutParams = layoutParams
|
||||
|
||||
parserIcon?.let {
|
||||
binding.extensionIconImageView.setImageDrawable(it)
|
||||
} ?: run {
|
||||
binding.extensionIconImageView.setImageResource(R.drawable.control_background_40dp)
|
||||
}
|
||||
|
||||
binding.extensionPinImageView.visibility = View.GONE
|
||||
binding.extensionVersionTextView.visibility = View.GONE
|
||||
binding.closeTextView.visibility = View.GONE
|
||||
binding.settingsImageView.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun updateSubscriptionCount() {
|
||||
binding.subscriptionCount.text = subscriptions.size.toString()
|
||||
binding.subscriptionCount.visibility = if (subscriptions.isEmpty()) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
private fun showRemoveAllSubscriptionsDialog(context: Context) {
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.remove_all_subscriptions)
|
||||
.setMessage(context.getString(R.string.remove_all_subscriptions_desc, parserName))
|
||||
.setPositiveButton(R.string.apply) { _, _ ->
|
||||
removeAllSubscriptions()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun removeAllSubscriptions() {
|
||||
subscriptions.forEach { subscription ->
|
||||
SubscriptionHelper.deleteSubscription(subscription.id, false)
|
||||
}
|
||||
if (isExpanded) {
|
||||
val startPosition = adapter.getAdapterPosition(this) + 1
|
||||
repeat(subscriptions.size) {
|
||||
adapter.removeGroupAtAdapterPosition(startPosition)
|
||||
}
|
||||
}
|
||||
subscriptions.clear()
|
||||
onGroupRemoved(this)
|
||||
}
|
||||
|
||||
private fun removeSubscription(id: Any?) {
|
||||
subscriptions.removeAll { it.id == id }
|
||||
updateSubscriptionCount()
|
||||
if (subscriptions.isEmpty()) {
|
||||
onGroupRemoved(this)
|
||||
} else {
|
||||
adapter.notifyItemChanged(adapter.getAdapterPosition(this))
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleSubscriptions() {
|
||||
val startPosition = adapter.getAdapterPosition(this) + 1
|
||||
if (isExpanded) {
|
||||
subscriptions.forEachIndexed { index, subscribeMedia ->
|
||||
adapter.add(startPosition + index, SubscriptionItem(subscribeMedia.id, subscribeMedia, adapter) { removedId ->
|
||||
removeSubscription(removedId)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
repeat(subscriptions.size) {
|
||||
adapter.removeGroupAtAdapterPosition(startPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayout(): Int = R.layout.item_extension
|
||||
|
||||
override fun initializeViewBinding(view: View): ItemExtensionBinding = ItemExtensionBinding.bind(view)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package ani.dantotsu.settings
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -9,13 +10,21 @@ import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.BottomSheetRecyclerBinding
|
||||
import ani.dantotsu.notifications.subscription.SubscriptionHelper
|
||||
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
|
||||
private var _binding: BottomSheetRecyclerBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val adapter: GroupieAdapter = GroupieAdapter()
|
||||
private var subscriptions: Map<Int, SubscriptionHelper.Companion.SubscribeMedia> = mapOf()
|
||||
private val animeExtension: AnimeExtensionManager = Injekt.get()
|
||||
private val mangaExtensions: MangaExtensionManager = Injekt.get()
|
||||
private val novelExtensions: NovelExtensionManager = Injekt.get()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
@@ -36,8 +45,33 @@ class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
|
||||
val context = requireContext()
|
||||
binding.title.text = context.getString(R.string.subscriptions)
|
||||
binding.replyButton.visibility = View.GONE
|
||||
subscriptions.forEach { (id, media) ->
|
||||
adapter.add(SubscriptionItem(id, media, adapter))
|
||||
|
||||
val groupedSubscriptions = subscriptions.values.groupBy {
|
||||
if (it.isAnime) SubscriptionHelper.getAnimeParser(it.id).name
|
||||
else SubscriptionHelper.getMangaParser(it.id).name
|
||||
}
|
||||
|
||||
groupedSubscriptions.forEach { (parserName, mediaList) ->
|
||||
adapter.add(SubscriptionSource(
|
||||
parserName,
|
||||
mediaList.toMutableList(),
|
||||
adapter,
|
||||
getParserIcon(parserName)
|
||||
) { group ->
|
||||
adapter.remove(group)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun getParserIcon(parserName: String): Drawable? {
|
||||
return when {
|
||||
animeExtension.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||
animeExtension.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||
mangaExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||
mangaExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||
novelExtensions.installedExtensionsFlow.value.any { it.name == parserName } ->
|
||||
novelExtensions.installedExtensionsFlow.value.find { it.name == parserName }?.icon
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
@@ -16,6 +15,7 @@ import ani.dantotsu.databinding.ActivityMarkdownCreatorBinding
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.others.AndroidBug5497Workaround
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
@@ -42,7 +42,7 @@ class ActivityMarkdownCreator : AppCompatActivity() {
|
||||
BOLD("****", 2, R.id.formatBold),
|
||||
ITALIC("**", 1, R.id.formatItalic),
|
||||
STRIKETHROUGH("~~~~", 2, R.id.formatStrikethrough),
|
||||
SPOILER("||", 2, R.id.formatSpoiler),
|
||||
SPOILER("~||~", 2, R.id.formatSpoiler),
|
||||
LINK("[Placeholder](%s)", 0, R.id.formatLink),
|
||||
IMAGE("img(%s)", 0, R.id.formatImage),
|
||||
YOUTUBE("youtube(%s)", 0, R.id.formatYoutube),
|
||||
@@ -68,6 +68,7 @@ class ActivityMarkdownCreator : AppCompatActivity() {
|
||||
bottomMargin += navBarHeight
|
||||
}
|
||||
setContentView(binding.root)
|
||||
AndroidBug5497Workaround.assistActivity(this) {}
|
||||
|
||||
val params = binding.createButton.layoutParams as ViewGroup.MarginLayoutParams
|
||||
params.marginEnd = 16 * resources.displayMetrics.density.toInt()
|
||||
|
||||
@@ -47,5 +47,9 @@ class NumberConverter {
|
||||
val intBits = java.lang.Float.floatToIntBits(number)
|
||||
return Integer.toBinaryString(intBits)
|
||||
}
|
||||
|
||||
fun Int.ofLength(length: Int): String {
|
||||
return this.toString().padStart(length, '0')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="32dp"
|
||||
android:layout_marginVertical="6dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="3dp"
|
||||
android:layout_marginEnd="9dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<LinearLayout
|
||||
@@ -53,6 +53,26 @@
|
||||
tools:ignore="SmallSp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subscriptionCount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:padding="12dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/extensionSubscriptions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="0"
|
||||
android:src="@drawable/ui_bg"
|
||||
android:visibility="gone"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/closeTextView"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
@@ -83,8 +83,7 @@
|
||||
<item>All</item>
|
||||
</string-array>
|
||||
|
||||
<string name="no_notifications">No more notifications</string>
|
||||
<string name="no_activities">No more activities</string>
|
||||
<string name="nothing_here">Nothing here</string>
|
||||
<string name="followers">Followers</string>
|
||||
<string name="write_a_message">Write a Message</string>
|
||||
<string name="status">STATUS</string>
|
||||
@@ -417,6 +416,8 @@
|
||||
<string name="use_alarm_manager_reliable">Use Alarm Manager for reliable Notifications</string>
|
||||
<string name="use_alarm_manager_confirm">Using Alarm Manger can help fight against battery optimization, but may consume more battery. It also requires the Alarm Manager permission.</string>
|
||||
<string name="use">Use</string>
|
||||
<string name="remove_all_subscriptions">Remove All Subscriptions</string>
|
||||
<string name="remove_all_subscriptions_desc">Are you sure you want to remove all subscriptions for %1$s?</string>
|
||||
<string name="checking_subscriptions">Notification for Checking Subscriptions</string>
|
||||
<string name="subscriptions_checking_time_s">Subscriptions Update Frequency : %1$s</string>
|
||||
<string name="subscriptions_checking_time">Subscriptions Update Frequency</string>
|
||||
|
||||
Reference in New Issue
Block a user