Merge branch 'dev' of https://github.com/rebelonion/Dantotsu into dev
This commit is contained in:
commit
c22fd6b66d
78 changed files with 1982 additions and 1674 deletions
|
@ -854,7 +854,7 @@ fun savePrefsToDownloads(
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
fun savePrefs(serialized: String, path: String, title: String, context: Context): File? {
|
||||
var file = File(path, "$title.ani")
|
||||
var counter = 1
|
||||
|
@ -874,6 +874,7 @@ fun savePrefs(serialized: String, path: String, title: String, context: Context)
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
fun savePrefs(
|
||||
serialized: String,
|
||||
path: String,
|
||||
|
@ -920,7 +921,7 @@ fun shareImage(title: String, bitmap: Bitmap, context: Context) {
|
|||
intent.putExtra(Intent.EXTRA_STREAM, contentUri)
|
||||
context.startActivity(Intent.createChooser(intent, "Share $title"))
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
fun saveImage(image: Bitmap, path: String, imageFileName: String): File? {
|
||||
val imageFile = File(path, "$imageFileName.png")
|
||||
return try {
|
||||
|
@ -1500,7 +1501,6 @@ fun buildMarkwon(
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
|
|
|
@ -61,6 +61,7 @@ import ani.dantotsu.settings.saving.internal.PreferenceKeystore
|
|||
import ani.dantotsu.settings.saving.internal.PreferencePackager
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
@ -312,6 +313,7 @@ class MainActivity : AppCompatActivity() {
|
|||
mainViewPager.adapter =
|
||||
ViewPagerAdapter(supportFragmentManager, lifecycle)
|
||||
mainViewPager.setPageTransformer(ZoomOutPageTransformer())
|
||||
mainViewPager.offscreenPageLimit = 1
|
||||
navbar.selectTabAt(selectedOption)
|
||||
navbar.setOnTabSelectListener(object :
|
||||
AnimatedBottomBar.OnTabSelectListener {
|
||||
|
@ -493,35 +495,28 @@ class MainActivity : AppCompatActivity() {
|
|||
val password = CharArray(16).apply { fill('0') }
|
||||
|
||||
// Inflate the dialog layout
|
||||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater)
|
||||
dialogView.userAgentTextBox.hint = "Password"
|
||||
dialogView.subtitle.visibility = View.VISIBLE
|
||||
dialogView.subtitle.text = getString(R.string.enter_password_to_decrypt_file)
|
||||
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Enter Password")
|
||||
.setView(dialogView.root)
|
||||
.setPositiveButton("OK", null)
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater).apply {
|
||||
userAgentTextBox.hint = "Password"
|
||||
subtitle.visibility = View.VISIBLE
|
||||
subtitle.text = getString(R.string.enter_password_to_decrypt_file)
|
||||
}
|
||||
customAlertDialog().apply {
|
||||
setTitle("Enter Password")
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.yes) {
|
||||
val editText = dialogView.userAgentTextBox
|
||||
if (editText.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.cancel) {
|
||||
password.fill('0')
|
||||
dialog.dismiss()
|
||||
callback(null)
|
||||
}
|
||||
.create()
|
||||
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
|
||||
// Override the positive button here
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val editText = dialog.findViewById<TextInputEditText>(R.id.userAgentTextBox)
|
||||
if (editText?.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
dialog.dismiss()
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,30 +93,41 @@ class AnilistMutations {
|
|||
)
|
||||
}
|
||||
|
||||
suspend fun postActivity(text: String, edit : Int? = null): String {
|
||||
suspend fun postActivity(text: String, edit: Int? = null): String {
|
||||
val encodedText = text.stringSanitizer()
|
||||
val query = "mutation{SaveTextActivity(${if (edit != null) "id:$edit," else ""} text:$encodedText){siteUrl}}"
|
||||
val query =
|
||||
"mutation{SaveTextActivity(${if (edit != null) "id:$edit," else ""} text:$encodedText){siteUrl}}"
|
||||
val result = executeQuery<JsonObject>(query)
|
||||
val errors = result?.get("errors")
|
||||
return errors?.toString()
|
||||
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
||||
}
|
||||
suspend fun postMessage(userId: Int, text: String, edit: Int? = null,isPrivate: Boolean = false): String {
|
||||
val encodedText = text.replace("","").stringSanitizer()
|
||||
val query = "mutation{SaveMessageActivity(${if (edit != null) "id:$edit," else ""} recipientId:$userId,message:$encodedText,private:$isPrivate){id}}"
|
||||
|
||||
suspend fun postMessage(
|
||||
userId: Int,
|
||||
text: String,
|
||||
edit: Int? = null,
|
||||
isPrivate: Boolean = false
|
||||
): String {
|
||||
val encodedText = text.replace("", "").stringSanitizer()
|
||||
val query =
|
||||
"mutation{SaveMessageActivity(${if (edit != null) "id:$edit," else ""} recipientId:$userId,message:$encodedText,private:$isPrivate){id}}"
|
||||
val result = executeQuery<JsonObject>(query)
|
||||
val errors = result?.get("errors")
|
||||
return errors?.toString()
|
||||
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
||||
}
|
||||
suspend fun postReply(activityId: Int, text: String, edit: Int? = null ): String {
|
||||
|
||||
suspend fun postReply(activityId: Int, text: String, edit: Int? = null): String {
|
||||
val encodedText = text.stringSanitizer()
|
||||
val query = "mutation{SaveActivityReply(${if (edit != null) "id:$edit," else ""} activityId:$activityId,text:$encodedText){id}}"
|
||||
val query =
|
||||
"mutation{SaveActivityReply(${if (edit != null) "id:$edit," else ""} activityId:$activityId,text:$encodedText){id}}"
|
||||
val result = executeQuery<JsonObject>(query)
|
||||
val errors = result?.get("errors")
|
||||
return errors?.toString()
|
||||
?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success")
|
||||
}
|
||||
|
||||
suspend fun postReview(summary: String, body: String, mediaId: Int, score: Int): String {
|
||||
val encodedSummary = summary.stringSanitizer()
|
||||
val encodedBody = body.stringSanitizer()
|
||||
|
@ -143,7 +154,6 @@ class AnilistMutations {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private fun String.stringSanitizer(): String {
|
||||
val sb = StringBuilder()
|
||||
var i = 0
|
||||
|
|
|
@ -479,6 +479,7 @@ class AnilistQueries {
|
|||
|
||||
suspend fun initHomePage(): Map<String, ArrayList<*>> {
|
||||
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
|
||||
|
@ -528,7 +529,7 @@ class AnilistQueries {
|
|||
current?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
|
@ -540,7 +541,7 @@ class AnilistQueries {
|
|||
repeating?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
|
@ -579,7 +580,7 @@ class AnilistQueries {
|
|||
current?.lists?.forEach { li ->
|
||||
li.entries?.reversed()?.forEach {
|
||||
val m = Media(it)
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
m.cameFromContinue = true
|
||||
subMap[m.id] = m
|
||||
} else {
|
||||
|
@ -612,7 +613,7 @@ class AnilistQueries {
|
|||
apiMediaList?.edges?.forEach {
|
||||
it.node?.let { i ->
|
||||
val m = Media(i).apply { isFav = true }
|
||||
if (m.id !in removeList) {
|
||||
if (m.id !in removeList && if (hidePrivate) !m.isListPrivate else true) {
|
||||
returnArray.add(m)
|
||||
} else {
|
||||
removedMedia.add(m)
|
||||
|
@ -1055,172 +1056,110 @@ query (${"$"}page: Int = 1, ${"$"}id: Int, ${"$"}type: MediaType, ${"$"}isAdult:
|
|||
return null
|
||||
}
|
||||
|
||||
private val onListAnime =
|
||||
(if (PrefManager.getVal(PrefName.IncludeAnimeList)) "" else "onList:false").replace(
|
||||
"\"",
|
||||
""
|
||||
)
|
||||
private val isAdult =
|
||||
(if (PrefManager.getVal(PrefName.AdultOnly)) "isAdult:true" else "").replace("\"", "")
|
||||
private fun mediaList(media1: Page?): ArrayList<Media> {
|
||||
val combinedList = arrayListOf<Media>()
|
||||
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 recentAnimeUpdates(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}airingSchedules(airingAt_greater:0 airingAt_lesser:${System.currentTimeMillis() / 1000 - 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}}}}"""
|
||||
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}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
}
|
||||
|
||||
private fun trendingMovies(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: ANIME, format: MOVIE, $onListAnime, $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 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 topRatedAnime(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort: SCORE_DESC, type: ANIME, $onListAnime, $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 mostFavAnime(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:FAVOURITES_DESC,type: ANIME, $onListAnime, $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 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>> {
|
||||
val list = mutableMapOf<String, ArrayList<Media>>()
|
||||
fun query(): String {
|
||||
return """{
|
||||
recentUpdates:${recentAnimeUpdates(1)}
|
||||
recentUpdates2:${recentAnimeUpdates(2)}
|
||||
trendingMovies:${trendingMovies(1)}
|
||||
trendingMovies2:${trendingMovies(2)}
|
||||
topRated:${topRatedAnime(1)}
|
||||
topRated2:${topRatedAnime(2)}
|
||||
mostFav:${mostFavAnime(1)}
|
||||
mostFav2:${mostFavAnime(2)}
|
||||
}""".trimIndent()
|
||||
}
|
||||
executeQuery<Query.AnimeList>(query(), force = true)?.data?.apply {
|
||||
|
||||
fun filterRecentUpdates(
|
||||
page: Page?,
|
||||
): ArrayList<Media> {
|
||||
val listOnly: Boolean = PrefManager.getVal(PrefName.RecentlyListOnly)
|
||||
val adultOnly: Boolean = PrefManager.getVal(PrefName.AdultOnly)
|
||||
val idArr = mutableListOf<Int>()
|
||||
list["recentUpdates"] = recentUpdates?.airingSchedules?.mapNotNull { i ->
|
||||
return page?.airingSchedules?.mapNotNull { i ->
|
||||
i.media?.let {
|
||||
if (!idArr.contains(it.id))
|
||||
if (!listOnly && it.countryOfOrigin == "JP" && Anilist.adult && adultOnly && it.isAdult == true) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if (!listOnly && !adultOnly && (it.countryOfOrigin == "JP" && it.isAdult == false)) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if ((listOnly && it.mediaListEntry != null)) {
|
||||
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
|
||||
else null
|
||||
} else null
|
||||
}
|
||||
}?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
|
||||
list["trendingMovies"] =
|
||||
trendingMovies?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["topRated"] =
|
||||
topRated?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["mostFav"] =
|
||||
mostFav?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
|
||||
list["recentUpdates"]?.addAll(recentUpdates2?.airingSchedules?.mapNotNull { i ->
|
||||
i.media?.let {
|
||||
if (!idArr.contains(it.id))
|
||||
if (!listOnly && it.countryOfOrigin == "JP" && Anilist.adult && adultOnly && it.isAdult == true) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if (!listOnly && !adultOnly && (it.countryOfOrigin == "JP" && it.isAdult == false)) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else if ((listOnly && it.mediaListEntry != null)) {
|
||||
idArr.add(it.id)
|
||||
Media(it)
|
||||
} else null
|
||||
else null
|
||||
}
|
||||
}?.toCollection(ArrayList()) ?: arrayListOf())
|
||||
list["trendingMovies"]?.addAll(trendingMovies2?.media?.map { Media(it) }
|
||||
?.toCollection(ArrayList()) ?: arrayListOf())
|
||||
list["topRated"]?.addAll(
|
||||
topRated2?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
)
|
||||
list["mostFav"]?.addAll(
|
||||
mostFav2?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
)
|
||||
}
|
||||
executeQuery<Query.AnimeList>(queryAnimeList(), force = true)?.data?.apply {
|
||||
list["recentUpdates"] = filterRecentUpdates(recentUpdates)
|
||||
list["trendingMovies"] = mediaList(trendingMovies)
|
||||
list["topRated"] = mediaList(topRated)
|
||||
list["mostFav"] = mediaList(mostFav)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
private val onListManga =
|
||||
(if (PrefManager.getVal(PrefName.IncludeMangaList)) "" else "onList:false").replace(
|
||||
"\"",
|
||||
""
|
||||
)
|
||||
|
||||
private fun trendingManga(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: MANGA,countryOfOrigin:JP, $onListManga, $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 trendingManhwa(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: MANGA, countryOfOrigin:KR, $onListManga, $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 trendingNovel(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:POPULARITY_DESC, type: MANGA, format: NOVEL, countryOfOrigin:JP, $onListManga, $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 topRatedManga(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort: SCORE_DESC, type: MANGA, $onListManga, $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 mostFavManga(page: Int): String {
|
||||
return """Page(page:$page,perPage:50){pageInfo{hasNextPage total}media(sort:FAVOURITES_DESC,type: MANGA, $onListManga, $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}}}"""
|
||||
}
|
||||
|
||||
suspend fun loadMangaList(): Map<String, ArrayList<Media>> {
|
||||
val list = mutableMapOf<String, ArrayList<Media>>()
|
||||
fun query(): String {
|
||||
return """{
|
||||
trendingManga:${trendingManga(1)}
|
||||
trendingManga2:${trendingManga(2)}
|
||||
trendingManhwa:${trendingManhwa(1)}
|
||||
trendingManhwa2:${trendingManhwa(2)}
|
||||
trendingNovel:${trendingNovel(1)}
|
||||
trendingNovel2:${trendingNovel(2)}
|
||||
topRated:${topRatedManga(1)}
|
||||
topRated2:${topRatedManga(2)}
|
||||
mostFav:${mostFavManga(1)}
|
||||
mostFav2:${mostFavManga(2)}
|
||||
}""".trimIndent()
|
||||
executeQuery<Query.MangaList>(queryMangaList(), force = true)?.data?.apply {
|
||||
list["trendingManga"] = mediaList(trendingManga)
|
||||
list["trendingManhwa"] = mediaList(trendingManhwa)
|
||||
list["trendingNovel"] = mediaList(trendingNovel)
|
||||
list["topRated"] = mediaList(topRated)
|
||||
list["mostFav"] = mediaList(mostFav)
|
||||
}
|
||||
|
||||
executeQuery<Query.MangaList>(query(), force = true)?.data?.apply {
|
||||
list["trendingManga"] =
|
||||
trendingManga?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["trendingManhwa"] =
|
||||
trendingManhwa?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["trendingNovel"] =
|
||||
trendingNovel?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["topRated"] =
|
||||
topRated?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
list["mostFav"] =
|
||||
mostFav?.media?.map { Media(it) }?.toCollection(ArrayList()) ?: arrayListOf()
|
||||
|
||||
list["trendingManga"]?.addAll(
|
||||
trendingManga2?.media?.map { Media(it) }?.toList() ?: arrayListOf()
|
||||
)
|
||||
list["trendingManhwa"]?.addAll(
|
||||
trendingManhwa2?.media?.map { Media(it) }?.toList() ?: arrayListOf()
|
||||
)
|
||||
list["trendingNovel"]?.addAll(
|
||||
trendingNovel2?.media?.map { Media(it) }?.toList() ?: arrayListOf()
|
||||
)
|
||||
list["topRated"]?.addAll(topRated2?.media?.map { Media(it) }?.toList() ?: arrayListOf())
|
||||
list["mostFav"]?.addAll(mostFav2?.media?.map { Media(it) }?.toList() ?: arrayListOf())
|
||||
}
|
||||
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
|
||||
suspend fun recentlyUpdated(
|
||||
greater: Long = 0,
|
||||
lesser: Long = System.currentTimeMillis() / 1000 - 10000
|
||||
|
|
|
@ -163,13 +163,9 @@ class Query {
|
|||
@Serializable
|
||||
data class Data(
|
||||
@SerialName("recentUpdates") val recentUpdates: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("recentUpdates2") val recentUpdates2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingMovies") val trendingMovies: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingMovies2") val trendingMovies2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated") val topRated: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated2") val topRated2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav") val mostFav: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav2") val mostFav2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -181,15 +177,10 @@ class Query {
|
|||
@Serializable
|
||||
data class Data(
|
||||
@SerialName("trendingManga") val trendingManga: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingManga2") val trendingManga2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingManhwa") val trendingManhwa: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingManhwa2") val trendingManhwa2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingNovel") val trendingNovel: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("trendingNovel2") val trendingNovel2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated") val topRated: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("topRated2") val topRated2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav") val mostFav: ani.dantotsu.connections.anilist.api.Page?,
|
||||
@SerialName("mostFav2") val mostFav2: ani.dantotsu.connections.anilist.api.Page?,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.anggrayudi.storage.file.openInputStream
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
|
@ -203,25 +204,22 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
|||
val type: MediaType = MediaType.ANIME
|
||||
|
||||
// Alert dialog to confirm deletion
|
||||
val builder =
|
||||
androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
builder.setTitle("Delete ${item.title}?")
|
||||
builder.setMessage("Are you sure you want to delete ${item.title}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
val mediaIds =
|
||||
PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values
|
||||
?: emptySet()
|
||||
if (mediaIds.isEmpty()) {
|
||||
snackString("No media found") // if this happens, terrible things have happened
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Delete ${item.title}?")
|
||||
setMessage("Are you sure you want to delete ${item.title}?")
|
||||
setPosButton(R.string.yes) {
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
val mediaIds = PrefManager.getAnimeDownloadPreferences().all?.filter { it.key.contains(item.title) }?.values ?: emptySet()
|
||||
if (mediaIds.isEmpty()) {
|
||||
snackString("No media found") // if this happens, terrible things have happened
|
||||
}
|
||||
getDownloads()
|
||||
}
|
||||
getDownloads()
|
||||
setNegButton(R.string.no) {
|
||||
// Do nothing
|
||||
}
|
||||
show()
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.anggrayudi.storage.file.openInputStream
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
|
@ -201,19 +202,15 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
|||
MediaType.NOVEL
|
||||
}
|
||||
// Alert dialog to confirm deletion
|
||||
val builder =
|
||||
androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
builder.setTitle("Delete ${item.title}?")
|
||||
builder.setMessage("Are you sure you want to delete ${item.title}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
getDownloads()
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Delete ${item.title}?")
|
||||
setMessage("Are you sure you want to delete ${item.title}?")
|
||||
setPosButton(R.string.yes) {
|
||||
downloadManager.removeMedia(item.title, type)
|
||||
getDownloads()
|
||||
}
|
||||
setNegButton(R.string.no)
|
||||
}.show()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package ani.dantotsu.download.video
|
|||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
|
@ -29,10 +28,10 @@ import ani.dantotsu.download.anime.AnimeDownloaderService
|
|||
import ani.dantotsu.download.anime.AnimeServiceDataSingleton
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.parsers.Subtitle
|
||||
import ani.dantotsu.parsers.Video
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
@ -72,19 +71,19 @@ object Helper {
|
|||
episodeImage
|
||||
)
|
||||
|
||||
val downloadsManger = Injekt.get<DownloadsManager>()
|
||||
val downloadCheck = downloadsManger
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
val downloadCheck = downloadsManager
|
||||
.queryDownload(title, episode, MediaType.ANIME)
|
||||
|
||||
if (downloadCheck) {
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle("Download Exists")
|
||||
.setMessage("A download for this episode already exists. Do you want to overwrite it?")
|
||||
.setPositiveButton("Yes") { _, _ ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle("Download Exists")
|
||||
setMessage("A download for this episode already exists. Do you want to overwrite it?")
|
||||
setPosButton(R.string.yes) {
|
||||
PrefManager.getAnimeDownloadPreferences().edit()
|
||||
.remove(animeDownloadTask.getTaskName())
|
||||
.apply()
|
||||
downloadsManger.removeDownload(
|
||||
downloadsManager.removeDownload(
|
||||
DownloadedType(
|
||||
title,
|
||||
episode,
|
||||
|
@ -99,8 +98,9 @@ object Helper {
|
|||
}
|
||||
}
|
||||
}
|
||||
.setNegativeButton("No") { _, _ -> }
|
||||
.show()
|
||||
setNegButton(R.string.no)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
AnimeServiceDataSingleton.downloadQueue.offer(animeDownloadTask)
|
||||
if (!AnimeServiceDataSingleton.isServiceRunning) {
|
||||
|
|
|
@ -482,13 +482,12 @@ class HomeFragment : Fragment() {
|
|||
CoroutineScope(Dispatchers.IO).launch {
|
||||
model.setListImages()
|
||||
}
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
model.initUserStatus()
|
||||
}
|
||||
|
||||
var empty = true
|
||||
val homeLayoutShow: List<Boolean> =
|
||||
PrefManager.getVal(PrefName.HomeLayout)
|
||||
model.initHomePage()
|
||||
model.initUserStatus()
|
||||
(array.indices).forEach { i ->
|
||||
if (homeLayoutShow.elementAt(i)) {
|
||||
empty = false
|
||||
|
|
|
@ -12,12 +12,14 @@ import androidx.documentfile.provider.DocumentFile
|
|||
import androidx.fragment.app.Fragment
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.databinding.DialogUserAgentBinding
|
||||
import ani.dantotsu.databinding.FragmentLoginBinding
|
||||
import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.settings.saving.internal.PreferenceKeystore
|
||||
import ani.dantotsu.settings.saving.internal.PreferencePackager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
class LoginFragment : Fragment() {
|
||||
|
@ -94,38 +96,31 @@ class LoginFragment : Fragment() {
|
|||
val password = CharArray(16).apply { fill('0') }
|
||||
|
||||
// Inflate the dialog layout
|
||||
val dialogView =
|
||||
LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_user_agent, null)
|
||||
dialogView.findViewById<TextInputEditText>(R.id.userAgentTextBox)?.hint = "Password"
|
||||
val subtitleTextView = dialogView.findViewById<TextView>(R.id.subtitle)
|
||||
subtitleTextView?.visibility = View.VISIBLE
|
||||
subtitleTextView?.text = "Enter your password to decrypt the file"
|
||||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater).apply {
|
||||
userAgentTextBox.hint = "Password"
|
||||
subtitle.visibility = View.VISIBLE
|
||||
subtitle.text = getString(R.string.enter_password_to_decrypt_file)
|
||||
}
|
||||
|
||||
val dialog = AlertDialog.Builder(requireActivity(), R.style.MyPopup)
|
||||
.setTitle("Enter Password")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK", null)
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
requireActivity().customAlertDialog().apply {
|
||||
setTitle("Enter Password")
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.ok){
|
||||
val editText = dialogView.userAgentTextBox
|
||||
if (editText.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.cancel) {
|
||||
password.fill('0')
|
||||
dialog.dismiss()
|
||||
callback(null)
|
||||
}
|
||||
.create()
|
||||
}.show()
|
||||
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
|
||||
// Override the positive button here
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val editText = dialog.findViewById<TextInputEditText>(R.id.userAgentTextBox)
|
||||
if (editText?.text?.isNotBlank() == true) {
|
||||
editText.text?.toString()?.trim()?.toCharArray(password)
|
||||
dialog.dismiss()
|
||||
callback(password)
|
||||
} else {
|
||||
toast("Password cannot be empty")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun restartApp() {
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
|
@ -16,7 +15,6 @@ import androidx.core.app.ActivityOptionsCompat
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
|
@ -32,6 +30,7 @@ import ani.dantotsu.profile.ProfileActivity
|
|||
import ani.dantotsu.profile.User
|
||||
import ani.dantotsu.profile.UsersDialogFragment
|
||||
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||
import ani.dantotsu.profile.activity.RepliesBottomDialog
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ani.dantotsu.home.status
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
|
@ -16,7 +15,7 @@ import ani.dantotsu.profile.User
|
|||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
|
||||
class UserStatusAdapter(private val user: ArrayList<User>) :
|
||||
RecyclerView.Adapter<UserStatusAdapter.UsersViewHolder>() {
|
||||
|
@ -43,7 +42,7 @@ class UserStatusAdapter(private val user: ArrayList<User>) :
|
|||
if (user[bindingAdapterPosition].id == Anilist.userid) {
|
||||
ContextCompat.startActivity(
|
||||
itemView.context,
|
||||
Intent(itemView.context, MarkdownCreatorActivity::class.java)
|
||||
Intent(itemView.context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "activity"),
|
||||
null
|
||||
)
|
||||
|
|
|
@ -30,6 +30,7 @@ class CalendarActivity : AppCompatActivity() {
|
|||
private lateinit var binding: ActivityListBinding
|
||||
private val scope = lifecycleScope
|
||||
private var selectedTabIdx = 1
|
||||
private var showOnlyLibrary = false
|
||||
private val model: OtherDetailsViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -38,8 +39,6 @@ class CalendarActivity : AppCompatActivity() {
|
|||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityListBinding.inflate(layoutInflater)
|
||||
|
||||
|
||||
|
||||
val primaryColor = getThemeColor(com.google.android.material.R.attr.colorSurface)
|
||||
val primaryTextColor = getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
||||
val secondaryTextColor = getThemeColor(com.google.android.material.R.attr.colorOutline)
|
||||
|
@ -79,6 +78,17 @@ class CalendarActivity : AppCompatActivity() {
|
|||
override fun onTabReselected(tab: TabLayout.Tab?) {}
|
||||
})
|
||||
|
||||
binding.listed.setOnClickListener {
|
||||
showOnlyLibrary = !showOnlyLibrary
|
||||
binding.listed.setImageResource(
|
||||
if (showOnlyLibrary) R.drawable.ic_round_collections_bookmark_24
|
||||
else R.drawable.ic_round_library_books_24
|
||||
)
|
||||
scope.launch {
|
||||
model.loadCalendar(showOnlyLibrary)
|
||||
}
|
||||
}
|
||||
|
||||
model.getCalendar().observe(this) {
|
||||
if (it != null) {
|
||||
binding.listProgressBar.visibility = View.GONE
|
||||
|
@ -97,11 +107,10 @@ class CalendarActivity : AppCompatActivity() {
|
|||
live.observe(this) {
|
||||
if (it) {
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) { model.loadCalendar() }
|
||||
withContext(Dispatchers.IO) { model.loadCalendar(showOnlyLibrary) }
|
||||
live.postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,25 +26,50 @@ class OtherDetailsViewModel : ViewModel() {
|
|||
if (author.value == null) author.postValue(Anilist.query.getAuthorDetails(m))
|
||||
}
|
||||
|
||||
private var cachedAllCalendarData: Map<String, MutableList<Media>>? = null
|
||||
private var cachedLibraryCalendarData: Map<String, MutableList<Media>>? = null
|
||||
private val calendar: MutableLiveData<Map<String, MutableList<Media>>> = MutableLiveData(null)
|
||||
fun getCalendar(): LiveData<Map<String, MutableList<Media>>> = calendar
|
||||
suspend fun loadCalendar() {
|
||||
val curr = System.currentTimeMillis() / 1000
|
||||
val res = Anilist.query.recentlyUpdated(curr - 86400, curr + (86400 * 6))
|
||||
val df = DateFormat.getDateInstance(DateFormat.FULL)
|
||||
val map = mutableMapOf<String, MutableList<Media>>()
|
||||
val idMap = mutableMapOf<String, MutableList<Int>>()
|
||||
res?.forEach {
|
||||
val v = it.relation?.split(",")?.map { i -> i.toLong() }!!
|
||||
val dateInfo = df.format(Date(v[1] * 1000))
|
||||
val list = map.getOrPut(dateInfo) { mutableListOf() }
|
||||
val idList = idMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
it.relation = "Episode ${v[0]}"
|
||||
if (!idList.contains(it.id)) {
|
||||
idList.add(it.id)
|
||||
list.add(it)
|
||||
suspend fun loadCalendar(showOnlyLibrary: Boolean = false) {
|
||||
if (cachedAllCalendarData == null || cachedLibraryCalendarData == null) {
|
||||
val curr = System.currentTimeMillis() / 1000
|
||||
val res = Anilist.query.recentlyUpdated(curr - 86400, curr + (86400 * 6))
|
||||
val df = DateFormat.getDateInstance(DateFormat.FULL)
|
||||
val allMap = mutableMapOf<String, MutableList<Media>>()
|
||||
val libraryMap = mutableMapOf<String, MutableList<Media>>()
|
||||
val idMap = mutableMapOf<String, MutableList<Int>>()
|
||||
|
||||
val userId = Anilist.userid ?: 0
|
||||
val userLibrary = Anilist.query.getMediaLists(true, userId)
|
||||
val libraryMediaIds = userLibrary.flatMap { it.value }.map { it.id }
|
||||
|
||||
res.forEach {
|
||||
val v = it.relation?.split(",")?.map { i -> i.toLong() }!!
|
||||
val dateInfo = df.format(Date(v[1] * 1000))
|
||||
val list = allMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
val libraryList = if (libraryMediaIds.contains(it.id)) {
|
||||
libraryMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val idList = idMap.getOrPut(dateInfo) { mutableListOf() }
|
||||
it.relation = "Episode ${v[0]}"
|
||||
if (!idList.contains(it.id)) {
|
||||
idList.add(it.id)
|
||||
list.add(it)
|
||||
libraryList?.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
cachedAllCalendarData = allMap
|
||||
cachedLibraryCalendarData = libraryMap
|
||||
}
|
||||
calendar.postValue(map)
|
||||
|
||||
val cacheToUse: Map<String, MutableList<Media>> = if (showOnlyLibrary) {
|
||||
cachedLibraryCalendarData ?: emptyMap()
|
||||
} else {
|
||||
cachedAllCalendarData ?: emptyMap()
|
||||
}
|
||||
calendar.postValue(cacheToUse)
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package ani.dantotsu.media
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableString
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -21,7 +20,7 @@ import ani.dantotsu.initActivity
|
|||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -59,7 +58,7 @@ class ReviewActivity : AppCompatActivity() {
|
|||
binding.followFilterButton.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
this,
|
||||
Intent(this, MarkdownCreatorActivity::class.java)
|
||||
Intent(this, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "review"),
|
||||
null
|
||||
)
|
||||
|
|
|
@ -183,6 +183,12 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
binding.searchByImage.setOnClickListener {
|
||||
activity.startActivity(Intent(activity, ImageSearchActivity::class.java))
|
||||
}
|
||||
binding.clearHistory.setOnClickListener {
|
||||
it.startAnimation(fadeOutAnimation())
|
||||
it.visibility = View.GONE
|
||||
searchHistoryAdapter.clearHistory()
|
||||
}
|
||||
updateClearHistoryVisibility()
|
||||
fun searchTitle() {
|
||||
activity.result.apply {
|
||||
search =
|
||||
|
@ -300,11 +306,17 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
}
|
||||
|
||||
binding.searchResultLayout.visibility = View.VISIBLE
|
||||
binding.clearHistory.visibility = View.GONE
|
||||
binding.searchHistoryList.visibility = View.GONE
|
||||
binding.searchByImage.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateClearHistoryVisibility() {
|
||||
binding.clearHistory.visibility =
|
||||
if (searchHistoryAdapter.itemCount > 0) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun fadeInAnimation(): Animation {
|
||||
return AlphaAnimation(0f, 1f).apply {
|
||||
duration = 150
|
||||
|
@ -375,4 +387,3 @@ class SearchAdapter(private val activity: SearchActivity, private val type: Stri
|
|||
override fun getItemCount(): Int = chips.size
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,12 @@ class SearchHistoryAdapter(private val type: String, private val searchClicked:
|
|||
PrefManager.setVal(historyType, searchHistory)
|
||||
}
|
||||
|
||||
fun clearHistory() {
|
||||
searchHistory?.clear()
|
||||
PrefManager.setVal(historyType, searchHistory)
|
||||
submitList(searchHistory?.toList())
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
|
|
|
@ -8,7 +8,6 @@ import android.view.ViewGroup
|
|||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.core.view.isGone
|
||||
|
@ -19,7 +18,7 @@ import ani.dantotsu.FileUrl
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.displayTimer
|
||||
import ani.dantotsu.isOnline
|
||||
|
@ -33,12 +32,14 @@ import ani.dantotsu.others.LanguageMapper
|
|||
import ani.dantotsu.others.webview.CookieCatcher
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.DynamicAnimeParser
|
||||
import ani.dantotsu.parsers.OfflineAnimeParser
|
||||
import ani.dantotsu.parsers.WatchSources
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.FAQActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.chip.Chip
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK
|
||||
|
@ -54,16 +55,13 @@ class AnimeWatchAdapter(
|
|||
) : RecyclerView.Adapter<AnimeWatchAdapter.ViewHolder>() {
|
||||
private var autoSelect = true
|
||||
var subscribe: MediaDetailsActivity.PopImageButton? = null
|
||||
private var _binding: ItemAnimeWatchBinding? = null
|
||||
private var _binding: ItemMediaSourceBinding? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val bind = ItemAnimeWatchBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val bind = ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(bind)
|
||||
}
|
||||
|
||||
private var nestedDialog: AlertDialog? = null
|
||||
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
_binding = binding
|
||||
|
@ -75,7 +73,7 @@ class AnimeWatchAdapter(
|
|||
null
|
||||
)
|
||||
}
|
||||
//Youtube
|
||||
// Youtube
|
||||
if (media.anime?.youtube != null && PrefManager.getVal(PrefName.ShowYtButton)) {
|
||||
binding.animeSourceYT.visibility = View.VISIBLE
|
||||
binding.animeSourceYT.setOnClickListener {
|
||||
|
@ -89,7 +87,7 @@ class AnimeWatchAdapter(
|
|||
R.string.subbed
|
||||
)
|
||||
|
||||
//PreferDub
|
||||
// PreferDub
|
||||
var changing = false
|
||||
binding.animeSourceDubbed.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.animeSourceDubbedText.text =
|
||||
|
@ -99,8 +97,8 @@ class AnimeWatchAdapter(
|
|||
if (!changing) fragment.onDubClicked(isChecked)
|
||||
}
|
||||
|
||||
//Wrong Title
|
||||
binding.animeSourceSearch.setOnClickListener {
|
||||
// Wrong Title
|
||||
binding.mediaSourceSearch.setOnClickListener {
|
||||
SourceSearchDialogFragment().show(
|
||||
fragment.requireActivity().supportFragmentManager,
|
||||
null
|
||||
|
@ -108,37 +106,37 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
|
||||
binding.animeSourceNameContainer.isGone = offline
|
||||
binding.animeSourceSettings.isGone = offline
|
||||
binding.animeSourceSearch.isGone = offline
|
||||
binding.animeSourceTitle.isGone = offline
|
||||
binding.mediaSourceNameContainer.isGone = offline
|
||||
binding.mediaSourceSettings.isGone = offline
|
||||
binding.mediaSourceSearch.isGone = offline
|
||||
binding.mediaSourceTitle.isGone = offline
|
||||
|
||||
//Source Selection
|
||||
// Source Selection
|
||||
var source =
|
||||
media.selected!!.sourceIndex.let { if (it >= watchSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex, source)
|
||||
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
|
||||
binding.animeSource.setText(watchSources.names[source])
|
||||
binding.mediaSource.setText(watchSources.names[source])
|
||||
watchSources[source].apply {
|
||||
this.selectDub = media.selected!!.preferDub
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
binding.animeSourceDubbedCont.isVisible = isDubAvailableSeparately()
|
||||
}
|
||||
}
|
||||
|
||||
binding.animeSource.setAdapter(
|
||||
binding.mediaSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
watchSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSourceTitle.isSelected = true
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceTitle.isSelected = true
|
||||
binding.mediaSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
changing = true
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
|
@ -150,15 +148,15 @@ class AnimeWatchAdapter(
|
|||
fragment.loadEpisodes(i, false)
|
||||
}
|
||||
|
||||
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
// Check if 'extension' and 'selected' properties exist and are accessible
|
||||
(watchSources[source] as? DynamicAnimeParser)?.let { ext ->
|
||||
ext.sourceLanguage = i
|
||||
fragment.onLangChange(i)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
changing = true
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
|
@ -170,19 +168,19 @@ class AnimeWatchAdapter(
|
|||
} ?: run { }
|
||||
}
|
||||
|
||||
//settings
|
||||
binding.animeSourceSettings.setOnClickListener {
|
||||
// Settings
|
||||
binding.mediaSourceSettings.setOnClickListener {
|
||||
(watchSources[source] as? DynamicAnimeParser)?.let { ext ->
|
||||
fragment.openSettings(ext.extension)
|
||||
}
|
||||
}
|
||||
|
||||
//Icons
|
||||
// Icons
|
||||
|
||||
//subscribe
|
||||
// Subscribe
|
||||
subscribe = MediaDetailsActivity.PopImageButton(
|
||||
fragment.lifecycleScope,
|
||||
binding.animeSourceSubscribe,
|
||||
binding.mediaSourceSubscribe,
|
||||
R.drawable.ic_round_notifications_active_24,
|
||||
R.drawable.ic_round_notifications_none_24,
|
||||
R.color.bg_opp,
|
||||
|
@ -190,117 +188,115 @@ class AnimeWatchAdapter(
|
|||
fragment.subscribed,
|
||||
true
|
||||
) {
|
||||
fragment.onNotificationPressed(it, binding.animeSource.text.toString())
|
||||
fragment.onNotificationPressed(it, binding.mediaSource.text.toString())
|
||||
}
|
||||
|
||||
subscribeButton(false)
|
||||
|
||||
binding.animeSourceSubscribe.setOnLongClickListener {
|
||||
binding.mediaSourceSubscribe.setOnLongClickListener {
|
||||
openSettings(fragment.requireContext(), CHANNEL_SUBSCRIPTION_CHECK)
|
||||
}
|
||||
|
||||
//Nested Button
|
||||
binding.animeNestedButton.setOnClickListener {
|
||||
val dialogView =
|
||||
LayoutInflater.from(fragment.requireContext()).inflate(R.layout.dialog_layout, null)
|
||||
val dialogBinding = DialogLayoutBinding.bind(dialogView)
|
||||
var refresh = false
|
||||
var run = false
|
||||
var reversed = media.selected!!.recyclerReversed
|
||||
var style =
|
||||
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.AnimeDefaultView)
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
dialogBinding.animeSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
//Grids
|
||||
var selected = when (style) {
|
||||
0 -> dialogBinding.animeSourceList
|
||||
1 -> dialogBinding.animeSourceGrid
|
||||
2 -> dialogBinding.animeSourceCompact
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> dialogBinding.layoutText.setText(R.string.list)
|
||||
1 -> dialogBinding.layoutText.setText(R.string.grid)
|
||||
2 -> dialogBinding.layoutText.setText(R.string.compact)
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
selected.alpha = 1f
|
||||
}
|
||||
dialogBinding.animeSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
dialogBinding.layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeSourceGrid.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
dialogBinding.layoutText.setText(R.string.grid)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 2
|
||||
dialogBinding.layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
// Nested Button
|
||||
binding.mediaNestedButton.setOnClickListener {
|
||||
val dialogBinding = DialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
dialogBinding.apply {
|
||||
var refresh = false
|
||||
var run = false
|
||||
var reversed = media.selected!!.recyclerReversed
|
||||
var style =
|
||||
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.AnimeDefaultView)
|
||||
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
mediaSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
//start CookieCatcher activity
|
||||
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
|
||||
val sourceAHH = watchSources[source] as? DynamicAnimeParser
|
||||
val sourceHttp =
|
||||
sourceAHH?.extension?.sources?.firstOrNull() as? AnimeHttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val headersMap = try {
|
||||
sourceHttp.headers.toMultimap()
|
||||
.mapValues { it.value.getOrNull(0) ?: "" }
|
||||
} catch (e: Exception) {
|
||||
emptyMap()
|
||||
// Grids
|
||||
var selected = when (style) {
|
||||
0 -> mediaSourceList
|
||||
1 -> mediaSourceGrid
|
||||
2 -> mediaSourceCompact
|
||||
else -> mediaSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> layoutText.setText(R.string.list)
|
||||
1 -> layoutText.setText(R.string.grid)
|
||||
2 -> layoutText.setText(R.string.compact)
|
||||
else -> mediaSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
selected.alpha = 1f
|
||||
}
|
||||
mediaSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
mediaSourceGrid.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
layoutText.setText(R.string.grid)
|
||||
run = true
|
||||
}
|
||||
mediaSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 2
|
||||
layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
mediaWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
}
|
||||
// Start CookieCatcher activity
|
||||
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
|
||||
val sourceAHH = watchSources[source] as? DynamicAnimeParser
|
||||
val sourceHttp =
|
||||
sourceAHH?.extension?.sources?.firstOrNull() as? AnimeHttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val headersMap = try {
|
||||
sourceHttp.headers.toMultimap()
|
||||
.mapValues { it.value.getOrNull(0) ?: "" }
|
||||
} catch (e: Exception) {
|
||||
emptyMap()
|
||||
}
|
||||
val intent =
|
||||
Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
.putExtra("headers", headersMap as HashMap<String, String>)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
.putExtra("headers", headersMap as HashMap<String, String>)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
}
|
||||
|
||||
// Hidden
|
||||
mangaScanlatorContainer.visibility = View.GONE
|
||||
animeDownloadContainer.visibility = View.GONE
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setTitle("Options")
|
||||
setCustomView(dialogBinding.root)
|
||||
setPosButton("OK") {
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
setNegButton("Cancel") {
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
//hidden
|
||||
dialogBinding.animeScanlatorContainer.visibility = View.GONE
|
||||
dialogBinding.animeDownloadContainer.visibility = View.GONE
|
||||
|
||||
nestedDialog = AlertDialog.Builder(fragment.requireContext(), R.style.MyPopup)
|
||||
.setTitle("Options")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
.setNegativeButton("Cancel") { _, _ ->
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
.setOnCancelListener {
|
||||
if (refresh) fragment.loadEpisodes(source, true)
|
||||
}
|
||||
.create()
|
||||
nestedDialog?.show()
|
||||
}
|
||||
//Episode Handling
|
||||
// Episode Handling
|
||||
handleEpisodes()
|
||||
}
|
||||
|
||||
|
@ -308,7 +304,7 @@ class AnimeWatchAdapter(
|
|||
subscribe?.enabled(enabled)
|
||||
}
|
||||
|
||||
//Chips
|
||||
// Chips
|
||||
fun updateChips(limit: Int, names: Array<String>, arr: Array<Int>, selected: Int = 0) {
|
||||
val binding = _binding
|
||||
if (binding != null) {
|
||||
|
@ -319,13 +315,13 @@ class AnimeWatchAdapter(
|
|||
val chip =
|
||||
ItemChipBinding.inflate(
|
||||
LayoutInflater.from(fragment.context),
|
||||
binding.animeSourceChipGroup,
|
||||
binding.mediaSourceChipGroup,
|
||||
false
|
||||
).root
|
||||
chip.isCheckable = true
|
||||
fun selected() {
|
||||
chip.isChecked = true
|
||||
binding.animeWatchChipScroll.smoothScrollTo(
|
||||
binding.mediaWatchChipScroll.smoothScrollTo(
|
||||
(chip.left - screenWidth / 2) + (chip.width / 2),
|
||||
0
|
||||
)
|
||||
|
@ -344,14 +340,14 @@ class AnimeWatchAdapter(
|
|||
selected()
|
||||
fragment.onChipClicked(position, limit * (position), last - 1)
|
||||
}
|
||||
binding.animeSourceChipGroup.addView(chip)
|
||||
binding.mediaSourceChipGroup.addView(chip)
|
||||
if (selected == position) {
|
||||
selected()
|
||||
select = chip
|
||||
}
|
||||
}
|
||||
if (select != null)
|
||||
binding.animeWatchChipScroll.apply {
|
||||
binding.mediaWatchChipScroll.apply {
|
||||
post {
|
||||
scrollTo(
|
||||
(select.left - screenWidth / 2) + (select.width / 2),
|
||||
|
@ -363,7 +359,7 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
|
||||
fun clearChips() {
|
||||
_binding?.animeSourceChipGroup?.removeAllViews()
|
||||
_binding?.mediaSourceChipGroup?.removeAllViews()
|
||||
}
|
||||
|
||||
fun handleEpisodes() {
|
||||
|
@ -379,15 +375,15 @@ class AnimeWatchAdapter(
|
|||
|
||||
var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString()
|
||||
if (episodes.contains(continueEp)) {
|
||||
binding.animeSourceContinue.visibility = View.VISIBLE
|
||||
binding.sourceContinue.visibility = View.VISIBLE
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
continueEp
|
||||
)
|
||||
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight > PrefManager.getVal<Float>(
|
||||
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight > PrefManager.getVal<Float>(
|
||||
PrefName.WatchPercentage
|
||||
)
|
||||
) {
|
||||
|
@ -395,9 +391,9 @@ class AnimeWatchAdapter(
|
|||
if (e != -1 && e + 1 < episodes.size) {
|
||||
continueEp = episodes[e + 1]
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
continueEp
|
||||
)
|
||||
|
@ -407,51 +403,63 @@ class AnimeWatchAdapter(
|
|||
|
||||
val cleanedTitle = ep.title?.let { MediaNameAdapter.removeEpisodeNumber(it) }
|
||||
|
||||
binding.itemEpisodeImage.loadImage(
|
||||
binding.itemMediaImage.loadImage(
|
||||
ep.thumb ?: FileUrl[media.banner ?: media.cover], 0
|
||||
)
|
||||
if (ep.filler) binding.itemEpisodeFillerView.visibility = View.VISIBLE
|
||||
|
||||
binding.animeSourceContinueText.text =
|
||||
binding.mediaSourceContinueText.text =
|
||||
currActivity()!!.getString(
|
||||
R.string.continue_episode, ep.number, if (ep.filler)
|
||||
currActivity()!!.getString(R.string.filler_tag)
|
||||
else
|
||||
"", cleanedTitle
|
||||
)
|
||||
binding.animeSourceContinue.setOnClickListener {
|
||||
binding.sourceContinue.setOnClickListener {
|
||||
fragment.onEpisodeClick(continueEp)
|
||||
}
|
||||
if (fragment.continueEp) {
|
||||
if (
|
||||
(binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams)
|
||||
(binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams)
|
||||
.weight < PrefManager.getVal<Float>(PrefName.WatchPercentage)
|
||||
) {
|
||||
binding.animeSourceContinue.performClick()
|
||||
binding.sourceContinue.performClick()
|
||||
fragment.continueEp = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.animeSourceProgressBar.visibility = View.GONE
|
||||
binding.sourceProgressBar.visibility = View.GONE
|
||||
|
||||
val sourceFound = media.anime.episodes!!.isNotEmpty()
|
||||
binding.animeSourceNotFound.isGone = sourceFound
|
||||
val isDownloadedSource = watchSources[media.selected!!.sourceIndex] is OfflineAnimeParser
|
||||
|
||||
if (isDownloadedSource) {
|
||||
binding.sourceNotFound.text = if (sourceFound) {
|
||||
currActivity()!!.getString(R.string.source_not_found)
|
||||
} else {
|
||||
currActivity()!!.getString(R.string.download_not_found)
|
||||
}
|
||||
} else {
|
||||
binding.sourceNotFound.text = currActivity()!!.getString(R.string.source_not_found)
|
||||
}
|
||||
|
||||
binding.sourceNotFound.isGone = sourceFound
|
||||
binding.faqbutton.isGone = sourceFound
|
||||
|
||||
if (!sourceFound && PrefManager.getVal(PrefName.SearchSources) && autoSelect) {
|
||||
if (binding.animeSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
if (binding.mediaSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
val nextIndex = media.selected!!.sourceIndex + 1
|
||||
binding.animeSource.setText(
|
||||
binding.animeSource.adapter
|
||||
binding.mediaSource.setText(
|
||||
binding.mediaSource.adapter
|
||||
.getItem(nextIndex).toString(), false
|
||||
)
|
||||
fragment.onSourceChange(nextIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
binding.animeSourceDubbedCont.isVisible = isDubAvailableSeparately()
|
||||
setLanguageList(0, nextIndex)
|
||||
|
@ -460,13 +468,13 @@ class AnimeWatchAdapter(
|
|||
fragment.loadEpisodes(nextIndex, false)
|
||||
}
|
||||
}
|
||||
binding.animeSource.setOnClickListener { autoSelect = false }
|
||||
binding.mediaSource.setOnClickListener { autoSelect = false }
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.animeSourceNotFound.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
binding.sourceNotFound.visibility = View.GONE
|
||||
binding.faqbutton.visibility = View.GONE
|
||||
clearChips()
|
||||
binding.animeSourceProgressBar.visibility = View.VISIBLE
|
||||
binding.sourceProgressBar.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -480,9 +488,9 @@ class AnimeWatchAdapter(
|
|||
ext.sourceLanguage = lang
|
||||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
binding?.mediaSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(
|
||||
binding?.mediaSourceLanguage?.setText(
|
||||
parser.extension.sources.firstOrNull()?.lang ?: "Unknown"
|
||||
)
|
||||
}
|
||||
|
@ -493,9 +501,9 @@ class AnimeWatchAdapter(
|
|||
)
|
||||
val items = adapter.count
|
||||
|
||||
binding?.animeSourceLanguageContainer?.visibility =
|
||||
binding?.mediaSourceLanguageContainer?.visibility =
|
||||
if (items > 1) View.VISIBLE else View.GONE
|
||||
binding?.animeSourceLanguage?.setAdapter(adapter)
|
||||
binding?.mediaSourceLanguage?.setAdapter(adapter)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -503,7 +511,7 @@ class AnimeWatchAdapter(
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) :
|
||||
inner class ViewHolder(val binding: ItemMediaSourceBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
displayTimer(media, binding.animeSourceContainer)
|
||||
|
|
|
@ -32,7 +32,7 @@ import ani.dantotsu.FileUrl
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.addons.download.DownloadAddonManager
|
||||
import ani.dantotsu.connections.anilist.api.MediaStreamingEpisode
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.compareName
|
||||
|
@ -63,6 +63,7 @@ import ani.dantotsu.toast
|
|||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.accessAlertDialog
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.hasDirAccess
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.anggrayudi.storage.file.extension
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
|
@ -80,7 +81,7 @@ import kotlin.math.max
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
class AnimeWatchFragment : Fragment() {
|
||||
private var _binding: FragmentAnimeWatchBinding? = null
|
||||
private var _binding: FragmentMediaSourceBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
||||
|
@ -107,7 +108,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentAnimeWatchBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentMediaSourceBinding.inflate(inflater, container, false)
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
|
@ -128,7 +129,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
)
|
||||
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
binding.mediaSourceRecycler.updatePadding(bottom = binding.mediaSourceRecycler.paddingBottom + navBarHeight)
|
||||
screenWidth = resources.displayMetrics.widthPixels.dp
|
||||
|
||||
var maxGridSize = (screenWidth / 100f).roundToInt()
|
||||
|
@ -152,13 +153,13 @@ class AnimeWatchFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
binding.animeSourceRecycler.layoutManager = gridLayoutManager
|
||||
binding.mediaSourceRecycler.layoutManager = gridLayoutManager
|
||||
|
||||
binding.ScrollTop.setOnClickListener {
|
||||
binding.animeSourceRecycler.scrollToPosition(10)
|
||||
binding.animeSourceRecycler.smoothScrollToPosition(0)
|
||||
binding.mediaSourceRecycler.scrollToPosition(10)
|
||||
binding.mediaSourceRecycler.smoothScrollToPosition(0)
|
||||
}
|
||||
binding.animeSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
binding.mediaSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
||||
|
@ -172,7 +173,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
}
|
||||
})
|
||||
model.scrolledToTop.observe(viewLifecycleOwner) {
|
||||
if (it) binding.animeSourceRecycler.scrollToPosition(0)
|
||||
if (it) binding.mediaSourceRecycler.scrollToPosition(0)
|
||||
}
|
||||
|
||||
continueEp = model.continueMedia ?: false
|
||||
|
@ -205,7 +206,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
offlineMode = offlineMode
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.adapter =
|
||||
binding.mediaSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, episodeAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -266,7 +267,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
}
|
||||
media.anime?.episodes = episodes
|
||||
|
||||
//CHIP GROUP
|
||||
// CHIP GROUP
|
||||
val total = episodes.size
|
||||
val divisions = total.toDouble() / 10
|
||||
start = 0
|
||||
|
@ -396,20 +397,18 @@ class AnimeWatchFragment : Fragment() {
|
|||
if (allSettings.size > 1) {
|
||||
val names =
|
||||
allSettings.map { LanguageMapper.getLanguageName(it.lang) }.toTypedArray()
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, -1) { dialog, which ->
|
||||
requireContext()
|
||||
.customAlertDialog()
|
||||
.apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names) { which ->
|
||||
selectedSetting = allSettings[which]
|
||||
itemSelected = true
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
requireActivity().runOnUiThread {
|
||||
val fragment =
|
||||
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
|
@ -417,13 +416,13 @@ class AnimeWatchFragment : Fragment() {
|
|||
.commit()
|
||||
}
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss {
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
requireActivity().runOnUiThread {
|
||||
|
@ -432,11 +431,12 @@ class AnimeWatchFragment : Fragment() {
|
|||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
parentFragmentManager.beginTransaction().apply {
|
||||
setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
addToBackStack(null)
|
||||
commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,7 +635,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest episode for subscription
|
||||
// Find latest episode for subscription
|
||||
selected.latest =
|
||||
media.anime?.episodes?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
|
@ -679,14 +679,14 @@ class AnimeWatchFragment : Fragment() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
binding.animeSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
binding.mediaSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
|
||||
requireActivity().setNavigationTheme()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
state = binding.animeSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
state = binding.mediaSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -23,6 +23,7 @@ import ani.dantotsu.media.MediaNameAdapter
|
|||
import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -106,8 +107,8 @@ class EpisodeAdapter(
|
|||
|
||||
val thumb =
|
||||
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
|
||||
Glide.with(binding.itemEpisodeImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemEpisodeImage)
|
||||
Glide.with(binding.itemMediaImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemMediaImage)
|
||||
binding.itemEpisodeNumber.text = ep.number
|
||||
binding.itemEpisodeTitle.text = if (ep.number == title) "Episode $title" else title
|
||||
|
||||
|
@ -140,9 +141,9 @@ class EpisodeAdapter(
|
|||
}
|
||||
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
ep.number
|
||||
)
|
||||
|
@ -154,8 +155,8 @@ class EpisodeAdapter(
|
|||
|
||||
val thumb =
|
||||
ep.thumb?.let { if (it.url.isNotEmpty()) GlideUrl(it.url) { it.headers } else null }
|
||||
Glide.with(binding.itemEpisodeImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemEpisodeImage)
|
||||
Glide.with(binding.itemMediaImage).load(thumb ?: media.cover).override(400, 0)
|
||||
.into(binding.itemMediaImage)
|
||||
|
||||
binding.itemEpisodeNumber.text = ep.number
|
||||
binding.itemEpisodeTitle.text = title
|
||||
|
@ -183,9 +184,9 @@ class EpisodeAdapter(
|
|||
binding.itemEpisodeViewed.visibility = View.GONE
|
||||
}
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
ep.number
|
||||
)
|
||||
|
@ -208,9 +209,9 @@ class EpisodeAdapter(
|
|||
}
|
||||
}
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
ep.number
|
||||
)
|
||||
|
@ -318,16 +319,14 @@ class EpisodeAdapter(
|
|||
fragment.onAnimeEpisodeStopDownloadClick(episodeNumber)
|
||||
return@setOnClickListener
|
||||
} else if (downloadedEpisodes.contains(episodeNumber)) {
|
||||
val builder = AlertDialog.Builder(currContext(), R.style.MyPopup)
|
||||
builder.setTitle("Delete Episode")
|
||||
builder.setMessage("Are you sure you want to delete Episode ${episodeNumber}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
fragment.onAnimeEpisodeRemoveDownloadClick(episodeNumber)
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
binding.root.context.customAlertDialog().apply {
|
||||
setTitle("Delete Episode")
|
||||
setMessage("Are you sure you want to delete Episode $episodeNumber?")
|
||||
setPosButton(R.string.yes) {
|
||||
fragment.onAnimeEpisodeRemoveDownloadClick(episodeNumber)
|
||||
}
|
||||
setNegButton(R.string.no)
|
||||
}.show()
|
||||
return@setOnClickListener
|
||||
} else {
|
||||
fragment.onAnimeEpisodeDownloadClick(episodeNumber)
|
||||
|
|
|
@ -444,15 +444,12 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
if (subtitles.isNotEmpty()) {
|
||||
val subtitleNames = subtitles.map { it.language }
|
||||
var subtitleToDownload: Subtitle? = null
|
||||
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.download_subtitle)
|
||||
.setSingleChoiceItems(
|
||||
subtitleNames.toTypedArray(),
|
||||
-1
|
||||
) { _, which ->
|
||||
requireActivity().customAlertDialog().apply {
|
||||
setTitle(R.string.download_subtitle)
|
||||
singleChoiceItems(subtitleNames.toTypedArray()) {which ->
|
||||
subtitleToDownload = subtitles[which]
|
||||
}
|
||||
.setPositiveButton(R.string.download) { dialog, _ ->
|
||||
setPosButton(R.string.download) {
|
||||
scope.launch {
|
||||
if (subtitleToDownload != null) {
|
||||
SubtitleDownloader.downloadSubtitle(
|
||||
|
@ -466,13 +463,9 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
)
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
setNegButton(R.string.cancel) {}
|
||||
}.show()
|
||||
} else {
|
||||
snackString(R.string.no_subtitles_available)
|
||||
}
|
||||
|
@ -576,65 +569,63 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
if (audioTracks.isNotEmpty()) {
|
||||
val audioNamesArray = audioTracks.toTypedArray()
|
||||
val checkedItems = BooleanArray(audioNamesArray.size) { false }
|
||||
val alertDialog = AlertDialog.Builder(currContext, R.style.MyPopup)
|
||||
.setTitle(R.string.download_audio_tracks)
|
||||
.setMultiChoiceItems(audioNamesArray, checkedItems) { _, which, isChecked ->
|
||||
val audioPair = Pair(extractor.audioTracks[which].url, extractor.audioTracks[which].lang)
|
||||
if (isChecked) {
|
||||
selectedAudioTracks.add(audioPair)
|
||||
} else {
|
||||
selectedAudioTracks.remove(audioPair)
|
||||
|
||||
currContext.customAlertDialog().apply{ // ToTest
|
||||
setTitle(R.string.download_audio_tracks)
|
||||
multiChoiceItems(audioNamesArray, checkedItems) {
|
||||
it.forEachIndexed { index, isChecked ->
|
||||
val audioPair = Pair(extractor.audioTracks[index].url, extractor.audioTracks[index].lang)
|
||||
if (isChecked) {
|
||||
selectedAudioTracks.add(audioPair)
|
||||
} else {
|
||||
selectedAudioTracks.remove(audioPair)
|
||||
}
|
||||
}
|
||||
}
|
||||
.setPositiveButton(R.string.download) { _, _ ->
|
||||
dialog?.dismiss()
|
||||
setPosButton(R.string.download) {
|
||||
go()
|
||||
}
|
||||
.setNegativeButton(R.string.skip) { dialog, _ ->
|
||||
setNegButton(R.string.skip) {
|
||||
selectedAudioTracks = mutableListOf()
|
||||
go()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||
setNeutralButton(R.string.cancel) {
|
||||
selectedAudioTracks = mutableListOf()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
go()
|
||||
}
|
||||
}
|
||||
if (subtitles.isNotEmpty()) {
|
||||
if (subtitles.isNotEmpty()) { // ToTest
|
||||
val subtitleNamesArray = subtitleNames.toTypedArray()
|
||||
val checkedItems = BooleanArray(subtitleNamesArray.size) { false }
|
||||
|
||||
val alertDialog = AlertDialog.Builder(currContext, R.style.MyPopup)
|
||||
.setTitle(R.string.download_subtitle)
|
||||
.setMultiChoiceItems(subtitleNamesArray, checkedItems) { _, which, isChecked ->
|
||||
val subtitlePair = Pair(subtitles[which].file.url, subtitles[which].language)
|
||||
if (isChecked) {
|
||||
selectedSubtitles.add(subtitlePair)
|
||||
} else {
|
||||
selectedSubtitles.remove(subtitlePair)
|
||||
currContext.customAlertDialog().apply {
|
||||
setTitle(R.string.download_subtitle)
|
||||
multiChoiceItems(subtitleNamesArray, checkedItems) {
|
||||
it.forEachIndexed { index, isChecked ->
|
||||
val subtitlePair = Pair(subtitles[index].file.url, subtitles[index].language)
|
||||
if (isChecked) {
|
||||
selectedSubtitles.add(subtitlePair)
|
||||
} else {
|
||||
selectedSubtitles.remove(subtitlePair)
|
||||
}
|
||||
}
|
||||
}
|
||||
.setPositiveButton(R.string.download) { _, _ ->
|
||||
dialog?.dismiss()
|
||||
setPosButton(R.string.download) {
|
||||
checkAudioTracks()
|
||||
}
|
||||
.setNegativeButton(R.string.skip) { dialog, _ ->
|
||||
setNegButton(R.string.skip) {
|
||||
selectedSubtitles = mutableListOf()
|
||||
checkAudioTracks()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||
setNeutralButton(R.string.cancel) {
|
||||
selectedSubtitles = mutableListOf()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
checkAudioTracks()
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import ani.dantotsu.setAnimation
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.ColorEditor.Companion.adjustColorForContrast
|
||||
import ani.dantotsu.util.ColorEditor.Companion.getContrastRatio
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.Section
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
|
@ -385,19 +386,14 @@ class CommentItem(
|
|||
* @param callback the callback to call when the user clicks yes
|
||||
*/
|
||||
private fun dialogBuilder(title: String, message: String, callback: () -> Unit) {
|
||||
val alertDialog =
|
||||
android.app.AlertDialog.Builder(commentsFragment.activity, R.style.MyPopup)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton("Yes") { dialog, _ ->
|
||||
callback()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("No") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
commentsFragment.activity.customAlertDialog().apply {
|
||||
setTitle(title)
|
||||
setMessage(message)
|
||||
setPosButton("Yes") {
|
||||
callback()
|
||||
}
|
||||
setNegButton("No") {}
|
||||
}.show()
|
||||
}
|
||||
|
||||
private val usernameColors: Array<String> = arrayOf(
|
||||
|
|
|
@ -25,6 +25,7 @@ import ani.dantotsu.connections.anilist.Anilist
|
|||
import ani.dantotsu.connections.comments.Comment
|
||||
import ani.dantotsu.connections.comments.CommentResponse
|
||||
import ani.dantotsu.connections.comments.CommentsAPI
|
||||
import ani.dantotsu.databinding.DialogEdittextBinding
|
||||
import ani.dantotsu.databinding.FragmentCommentsBinding
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
|
@ -34,6 +35,7 @@ import ani.dantotsu.settings.saving.PrefName
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.Section
|
||||
import io.noties.markwon.editor.MarkwonEditor
|
||||
|
@ -162,33 +164,26 @@ class CommentsFragment : Fragment() {
|
|||
}
|
||||
|
||||
binding.commentFilter.setOnClickListener {
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Enter a chapter/episode number tag")
|
||||
.setView(R.layout.dialog_edittext)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
val editText =
|
||||
(dialog as AlertDialog).findViewById<EditText>(R.id.dialogEditText)
|
||||
val text = editText?.text.toString()
|
||||
activity.customAlertDialog().apply {
|
||||
val customView = DialogEdittextBinding.inflate(layoutInflater)
|
||||
setTitle("Enter a chapter/episode number tag")
|
||||
setCustomView(customView.root)
|
||||
setPosButton("OK") {
|
||||
val text = customView.dialogEditText.text.toString()
|
||||
filterTag = text.toIntOrNull()
|
||||
lifecycleScope.launch {
|
||||
loadAndDisplayComments()
|
||||
}
|
||||
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton("Clear") { dialog, _ ->
|
||||
setNeutralButton("Clear") {
|
||||
filterTag = null
|
||||
lifecycleScope.launch {
|
||||
loadAndDisplayComments()
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
filterTag = null
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
setNegButton("Cancel") { filterTag = null }
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
var isFetching = false
|
||||
|
@ -303,13 +298,12 @@ class CommentsFragment : Fragment() {
|
|||
|
||||
activity.binding.commentLabel.setOnClickListener {
|
||||
//alert dialog to enter a number, with a cancel and ok button
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Enter a chapter/episode number tag")
|
||||
.setView(R.layout.dialog_edittext)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
val editText =
|
||||
(dialog as AlertDialog).findViewById<EditText>(R.id.dialogEditText)
|
||||
val text = editText?.text.toString()
|
||||
activity.customAlertDialog().apply {
|
||||
val customView = DialogEdittextBinding.inflate(layoutInflater)
|
||||
setTitle("Enter a chapter/episode number tag")
|
||||
setCustomView(customView.root)
|
||||
setPosButton("OK") {
|
||||
val text = customView.dialogEditText.text.toString()
|
||||
tag = text.toIntOrNull()
|
||||
if (tag == null) {
|
||||
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
|
||||
|
@ -324,28 +318,25 @@ class CommentsFragment : Fragment() {
|
|||
null
|
||||
)
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton("Clear") { dialog, _ ->
|
||||
setNeutralButton("Clear") {
|
||||
tag = null
|
||||
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
R.drawable.ic_label_off_24,
|
||||
null
|
||||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
setNegButton("Cancel") {
|
||||
tag = null
|
||||
activity.binding.commentLabel.background = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
R.drawable.ic_label_off_24,
|
||||
null
|
||||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,12 +353,6 @@ class CommentsFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
@ -579,9 +564,9 @@ class CommentsFragment : Fragment() {
|
|||
* Called when the user tries to comment for the first time
|
||||
*/
|
||||
private fun showCommentRulesDialog() {
|
||||
val alertDialog = AlertDialog.Builder(activity, R.style.MyPopup)
|
||||
.setTitle("Commenting Rules")
|
||||
.setMessage(
|
||||
activity.customAlertDialog().apply{
|
||||
setTitle("Commenting Rules")
|
||||
setMessage(
|
||||
"I WILL BAN YOU WITHOUT HESITATION\n" +
|
||||
"1. No racism\n" +
|
||||
"2. No hate speech\n" +
|
||||
|
@ -594,16 +579,13 @@ class CommentsFragment : Fragment() {
|
|||
"10. No illegal content\n" +
|
||||
"11. Anything you know you shouldn't comment\n"
|
||||
)
|
||||
.setPositiveButton("I Understand") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
setPosButton("I Understand") {
|
||||
PrefManager.setVal(PrefName.FirstComment, false)
|
||||
processComment()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
val dialog = alertDialog.show()
|
||||
dialog?.window?.setDimAmount(0.8f)
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun processComment() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ani.dantotsu.media.manga
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -19,8 +18,9 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.CustomDialogLayoutBinding
|
||||
import ani.dantotsu.databinding.DialogLayoutBinding
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemMediaSourceBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.isOnline
|
||||
import ani.dantotsu.loadImage
|
||||
|
@ -35,11 +35,13 @@ import ani.dantotsu.others.webview.CookieCatcher
|
|||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.MangaReadSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.parsers.OfflineMangaParser
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.FAQActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.chip.Chip
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
|
@ -55,31 +57,29 @@ class MangaReadAdapter(
|
|||
) : RecyclerView.Adapter<MangaReadAdapter.ViewHolder>() {
|
||||
|
||||
var subscribe: MediaDetailsActivity.PopImageButton? = null
|
||||
private var _binding: ItemAnimeWatchBinding? = null
|
||||
private var _binding: ItemMediaSourceBinding? = null
|
||||
val hiddenScanlators = mutableListOf<String>()
|
||||
var scanlatorSelectionListener: ScanlatorSelectionListener? = null
|
||||
var options = listOf<String>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val bind = ItemAnimeWatchBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val bind = ItemMediaSourceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(bind)
|
||||
}
|
||||
|
||||
private var nestedDialog: AlertDialog? = null
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
_binding = binding
|
||||
binding.sourceTitle.setText(R.string.chaps)
|
||||
|
||||
//Fuck u launch
|
||||
// Fuck u launch
|
||||
binding.faqbutton.setOnClickListener {
|
||||
val intent = Intent(fragment.requireContext(), FAQActivity::class.java)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
|
||||
//Wrong Title
|
||||
binding.animeSourceSearch.setOnClickListener {
|
||||
// Wrong Title
|
||||
binding.mediaSourceSearch.setOnClickListener {
|
||||
SourceSearchDialogFragment().show(
|
||||
fragment.requireActivity().supportFragmentManager,
|
||||
null
|
||||
|
@ -87,54 +87,54 @@ class MangaReadAdapter(
|
|||
}
|
||||
val offline = !isOnline(binding.root.context) || PrefManager.getVal(PrefName.OfflineMode)
|
||||
|
||||
binding.animeSourceNameContainer.isGone = offline
|
||||
binding.animeSourceSettings.isGone = offline
|
||||
binding.animeSourceSearch.isGone = offline
|
||||
binding.animeSourceTitle.isGone = offline
|
||||
//Source Selection
|
||||
binding.mediaSourceNameContainer.isGone = offline
|
||||
binding.mediaSourceSettings.isGone = offline
|
||||
binding.mediaSourceSearch.isGone = offline
|
||||
binding.mediaSourceTitle.isGone = offline
|
||||
// Source Selection
|
||||
var source =
|
||||
media.selected!!.sourceIndex.let { if (it >= mangaReadSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex, source)
|
||||
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
|
||||
binding.animeSource.setText(mangaReadSources.names[source])
|
||||
binding.mediaSource.setText(mangaReadSources.names[source])
|
||||
mangaReadSources[source].apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
}
|
||||
}
|
||||
media.selected?.scanlators?.let {
|
||||
hiddenScanlators.addAll(it)
|
||||
}
|
||||
binding.animeSource.setAdapter(
|
||||
binding.mediaSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
mangaReadSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSourceTitle.isSelected = true
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceTitle.isSelected = true
|
||||
binding.mediaSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
source = i
|
||||
setLanguageList(0, i)
|
||||
}
|
||||
subscribeButton(false)
|
||||
//invalidate if it's the last source
|
||||
// Invalidate if it's the last source
|
||||
val invalidate = i == mangaReadSources.names.size - 1
|
||||
fragment.loadChapters(i, invalidate)
|
||||
}
|
||||
|
||||
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
// Check if 'extension' and 'selected' properties exist and are accessible
|
||||
(mangaReadSources[source] as? DynamicMangaParser)?.let { ext ->
|
||||
ext.sourceLanguage = i
|
||||
fragment.onLangChange(i, ext.saveName)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
setLanguageList(i, source)
|
||||
}
|
||||
subscribeButton(false)
|
||||
|
@ -143,17 +143,17 @@ class MangaReadAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
//settings
|
||||
binding.animeSourceSettings.setOnClickListener {
|
||||
// Settings
|
||||
binding.mediaSourceSettings.setOnClickListener {
|
||||
(mangaReadSources[source] as? DynamicMangaParser)?.let { ext ->
|
||||
fragment.openSettings(ext.extension)
|
||||
}
|
||||
}
|
||||
|
||||
//Grids
|
||||
// Grids
|
||||
subscribe = MediaDetailsActivity.PopImageButton(
|
||||
fragment.lifecycleScope,
|
||||
binding.animeSourceSubscribe,
|
||||
binding.mediaSourceSubscribe,
|
||||
R.drawable.ic_round_notifications_active_24,
|
||||
R.drawable.ic_round_notifications_none_24,
|
||||
R.color.bg_opp,
|
||||
|
@ -161,206 +161,191 @@ class MangaReadAdapter(
|
|||
fragment.subscribed,
|
||||
true
|
||||
) {
|
||||
fragment.onNotificationPressed(it, binding.animeSource.text.toString())
|
||||
fragment.onNotificationPressed(it, binding.mediaSource.text.toString())
|
||||
}
|
||||
|
||||
subscribeButton(false)
|
||||
|
||||
binding.animeSourceSubscribe.setOnLongClickListener {
|
||||
binding.mediaSourceSubscribe.setOnLongClickListener {
|
||||
openSettings(fragment.requireContext(), CHANNEL_SUBSCRIPTION_CHECK)
|
||||
}
|
||||
|
||||
binding.animeNestedButton.setOnClickListener {
|
||||
|
||||
val dialogView =
|
||||
LayoutInflater.from(fragment.requireContext()).inflate(R.layout.dialog_layout, null)
|
||||
val dialogBinding = DialogLayoutBinding.bind(dialogView)
|
||||
binding.mediaNestedButton.setOnClickListener {
|
||||
val dialogBinding = DialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
var refresh = false
|
||||
var run = false
|
||||
var reversed = media.selected!!.recyclerReversed
|
||||
var style =
|
||||
media.selected!!.recyclerStyle ?: PrefManager.getVal(PrefName.MangaDefaultView)
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
dialogBinding.animeSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
dialogBinding.animeSourceTop.rotation = if (reversed) -90f else 90f
|
||||
dialogBinding.sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
dialogBinding.apply {
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
mediaSourceTop.setOnClickListener {
|
||||
reversed = !reversed
|
||||
mediaSourceTop.rotation = if (reversed) -90f else 90f
|
||||
sortText.text = if (reversed) "Down to Up" else "Up to Down"
|
||||
run = true
|
||||
}
|
||||
|
||||
//Grids
|
||||
dialogBinding.animeSourceGrid.visibility = View.GONE
|
||||
var selected = when (style) {
|
||||
0 -> dialogBinding.animeSourceList
|
||||
1 -> dialogBinding.animeSourceCompact
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> dialogBinding.layoutText.setText(R.string.list)
|
||||
1 -> dialogBinding.layoutText.setText(R.string.compact)
|
||||
else -> dialogBinding.animeSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
// Grids
|
||||
mediaSourceGrid.visibility = View.GONE
|
||||
var selected = when (style) {
|
||||
0 -> mediaSourceList
|
||||
1 -> mediaSourceCompact
|
||||
else -> mediaSourceList
|
||||
}
|
||||
when (style) {
|
||||
0 -> layoutText.setText(R.string.list)
|
||||
1 -> layoutText.setText(R.string.compact)
|
||||
else -> mediaSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
}
|
||||
dialogBinding.animeSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
dialogBinding.layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
dialogBinding.layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
dialogBinding.animeWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
fun selected(it: ImageButton) {
|
||||
selected.alpha = 0.33f
|
||||
selected = it
|
||||
selected.alpha = 1f
|
||||
}
|
||||
//start CookieCatcher activity
|
||||
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
|
||||
val sourceAHH = mangaReadSources[source] as? DynamicMangaParser
|
||||
val sourceHttp = sourceAHH?.extension?.sources?.firstOrNull() as? HttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val intent = Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
mediaSourceList.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 0
|
||||
layoutText.setText(R.string.list)
|
||||
run = true
|
||||
}
|
||||
mediaSourceCompact.setOnClickListener {
|
||||
selected(it as ImageButton)
|
||||
style = 1
|
||||
layoutText.setText(R.string.compact)
|
||||
run = true
|
||||
}
|
||||
mediaWebviewContainer.setOnClickListener {
|
||||
if (!WebViewUtil.supportsWebView(fragment.requireContext())) {
|
||||
toast(R.string.webview_not_installed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Multi download
|
||||
dialogBinding.downloadNo.text = "0"
|
||||
dialogBinding.animeDownloadTop.setOnClickListener {
|
||||
//Alert dialog asking for the number of chapters to download
|
||||
val alertDialog = AlertDialog.Builder(currContext(), R.style.MyPopup)
|
||||
alertDialog.setTitle("Multi Chapter Downloader")
|
||||
alertDialog.setMessage("Enter the number of chapters to download")
|
||||
val input = NumberPicker(currContext())
|
||||
input.minValue = 1
|
||||
input.maxValue = 20
|
||||
input.value = 1
|
||||
alertDialog.setView(input)
|
||||
alertDialog.setPositiveButton("OK") { _, _ ->
|
||||
dialogBinding.downloadNo.text = "${input.value}"
|
||||
}
|
||||
alertDialog.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() }
|
||||
val dialog = alertDialog.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
|
||||
//Scanlator
|
||||
dialogBinding.animeScanlatorContainer.isVisible = options.count() > 1
|
||||
dialogBinding.scanlatorNo.text = "${options.count()}"
|
||||
dialogBinding.animeScanlatorTop.setOnClickListener {
|
||||
val dialogView2 =
|
||||
LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
|
||||
val checkboxContainer =
|
||||
dialogView2.findViewById<LinearLayout>(R.id.checkboxContainer)
|
||||
val tickAllButton = dialogView2.findViewById<ImageButton>(R.id.toggleButton)
|
||||
|
||||
// Function to get the right image resource for the toggle button
|
||||
fun getToggleImageResource(container: ViewGroup): Int {
|
||||
var allChecked = true
|
||||
var allUnchecked = true
|
||||
|
||||
for (i in 0 until container.childCount) {
|
||||
val checkBox = container.getChildAt(i) as CheckBox
|
||||
if (!checkBox.isChecked) {
|
||||
allChecked = false
|
||||
} else {
|
||||
allUnchecked = false
|
||||
// Start CookieCatcher activity
|
||||
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
|
||||
val sourceAHH = mangaReadSources[source] as? DynamicMangaParser
|
||||
val sourceHttp = sourceAHH?.extension?.sources?.firstOrNull() as? HttpSource
|
||||
val url = sourceHttp?.baseUrl
|
||||
url?.let {
|
||||
refresh = true
|
||||
val intent =
|
||||
Intent(fragment.requireContext(), CookieCatcher::class.java)
|
||||
.putExtra("url", url)
|
||||
startActivity(fragment.requireContext(), intent, null)
|
||||
}
|
||||
}
|
||||
return when {
|
||||
allChecked -> R.drawable.untick_all_boxes
|
||||
allUnchecked -> R.drawable.tick_all_boxes
|
||||
else -> R.drawable.invert_all_boxes
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamically add checkboxes
|
||||
options.forEach { option ->
|
||||
val checkBox = CheckBox(currContext()).apply {
|
||||
text = option
|
||||
setOnCheckedChangeListener { _, _ ->
|
||||
// Update image resource when you change a checkbox
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
// Multi download
|
||||
downloadNo.text = "0"
|
||||
mediaDownloadTop.setOnClickListener {
|
||||
// Alert dialog asking for the number of chapters to download
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setTitle("Multi Chapter Downloader")
|
||||
setMessage("Enter the number of chapters to download")
|
||||
val input = NumberPicker(currContext())
|
||||
input.minValue = 1
|
||||
input.maxValue = 20
|
||||
input.value = 1
|
||||
setCustomView(input)
|
||||
setPosButton(R.string.ok) {
|
||||
downloadNo.text = "${input.value}"
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
|
||||
// Set checked if its already selected
|
||||
if (media.selected!!.scanlators != null) {
|
||||
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
} else {
|
||||
checkBox.isChecked = true
|
||||
}
|
||||
checkboxContainer.addView(checkBox)
|
||||
}
|
||||
|
||||
// Create AlertDialog
|
||||
val dialog = AlertDialog.Builder(currContext(), R.style.MyPopup)
|
||||
.setView(dialogView2)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
hiddenScanlators.clear()
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
// Scanlator
|
||||
mangaScanlatorContainer.isVisible = options.count() > 1
|
||||
scanlatorNo.text = "${options.count()}"
|
||||
mangaScanlatorTop.setOnClickListener {
|
||||
CustomDialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
val dialogView = CustomDialogLayoutBinding.inflate(fragment.layoutInflater)
|
||||
val checkboxContainer = dialogView.checkboxContainer
|
||||
val tickAllButton = dialogView.toggleButton
|
||||
|
||||
fun getToggleImageResource(container: ViewGroup): Int {
|
||||
var allChecked = true
|
||||
var allUnchecked = true
|
||||
|
||||
for (i in 0 until container.childCount) {
|
||||
val checkBox = container.getChildAt(i) as CheckBox
|
||||
if (!checkBox.isChecked) {
|
||||
hiddenScanlators.add(checkBox.text.toString())
|
||||
allChecked = false
|
||||
} else {
|
||||
allUnchecked = false
|
||||
}
|
||||
}
|
||||
fragment.onScanlatorChange(hiddenScanlators)
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
}
|
||||
.setNegativeButton("Cancel", null)
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
|
||||
// Standard image resource
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
|
||||
// Listens to ticked checkboxes and changes image resource accordingly
|
||||
tickAllButton.setOnClickListener {
|
||||
// Toggle checkboxes
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
checkBox.isChecked = !checkBox.isChecked
|
||||
return when {
|
||||
allChecked -> R.drawable.untick_all_boxes
|
||||
allUnchecked -> R.drawable.tick_all_boxes
|
||||
else -> R.drawable.invert_all_boxes
|
||||
}
|
||||
}
|
||||
|
||||
// Update image resource
|
||||
options.forEach { option ->
|
||||
val checkBox = CheckBox(currContext()).apply {
|
||||
text = option
|
||||
setOnCheckedChangeListener { _, _ ->
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
}
|
||||
}
|
||||
|
||||
if (media.selected!!.scanlators != null) {
|
||||
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
} else {
|
||||
checkBox.isChecked = true
|
||||
}
|
||||
checkboxContainer.addView(checkBox)
|
||||
}
|
||||
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton("OK") {
|
||||
hiddenScanlators.clear()
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
if (!checkBox.isChecked) {
|
||||
hiddenScanlators.add(checkBox.text.toString())
|
||||
}
|
||||
}
|
||||
fragment.onScanlatorChange(hiddenScanlators)
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
}
|
||||
setNegButton("Cancel")
|
||||
}.show()
|
||||
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
|
||||
tickAllButton.setOnClickListener {
|
||||
for (i in 0 until checkboxContainer.childCount) {
|
||||
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
|
||||
checkBox.isChecked = !checkBox.isChecked
|
||||
}
|
||||
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
|
||||
}
|
||||
}
|
||||
|
||||
fragment.requireContext().customAlertDialog().apply {
|
||||
setTitle("Options")
|
||||
setCustomView(root)
|
||||
setPosButton("OK") {
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (downloadNo.text != "0") {
|
||||
fragment.multiDownload(downloadNo.text.toString().toInt())
|
||||
}
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
setNegButton("Cancel") {
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
nestedDialog = AlertDialog.Builder(fragment.requireContext(), R.style.MyPopup)
|
||||
.setTitle("Options")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
if (run) fragment.onIconPressed(style, reversed)
|
||||
if (dialogBinding.downloadNo.text != "0") {
|
||||
fragment.multiDownload(dialogBinding.downloadNo.text.toString().toInt())
|
||||
}
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
.setNegativeButton("Cancel") { _, _ ->
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
.setOnCancelListener {
|
||||
if (refresh) fragment.loadChapters(source, true)
|
||||
}
|
||||
.create()
|
||||
nestedDialog?.show()
|
||||
}
|
||||
//Chapter Handling
|
||||
// Chapter Handling
|
||||
handleChapters()
|
||||
}
|
||||
|
||||
|
@ -368,7 +353,7 @@ class MangaReadAdapter(
|
|||
subscribe?.enabled(enabled)
|
||||
}
|
||||
|
||||
//Chips
|
||||
// Chips
|
||||
fun updateChips(limit: Int, names: Array<String>, arr: Array<Int>, selected: Int = 0) {
|
||||
val binding = _binding
|
||||
if (binding != null) {
|
||||
|
@ -379,13 +364,13 @@ class MangaReadAdapter(
|
|||
val chip =
|
||||
ItemChipBinding.inflate(
|
||||
LayoutInflater.from(fragment.context),
|
||||
binding.animeSourceChipGroup,
|
||||
binding.mediaSourceChipGroup,
|
||||
false
|
||||
).root
|
||||
chip.isCheckable = true
|
||||
fun selected() {
|
||||
chip.isChecked = true
|
||||
binding.animeWatchChipScroll.smoothScrollTo(
|
||||
binding.mediaWatchChipScroll.smoothScrollTo(
|
||||
(chip.left - screenWidth / 2) + (chip.width / 2),
|
||||
0
|
||||
)
|
||||
|
@ -403,7 +388,7 @@ class MangaReadAdapter(
|
|||
} else {
|
||||
names[last - 1]
|
||||
}
|
||||
//chip.text = "${names[limit * (position)]} - ${names[last - 1]}"
|
||||
// chip.text = "${names[limit * (position)]} - ${names[last - 1]}"
|
||||
val chipText = "$startChapterString - $endChapterString"
|
||||
chip.text = chipText
|
||||
chip.setTextColor(
|
||||
|
@ -417,14 +402,14 @@ class MangaReadAdapter(
|
|||
selected()
|
||||
fragment.onChipClicked(position, limit * (position), last - 1)
|
||||
}
|
||||
binding.animeSourceChipGroup.addView(chip)
|
||||
binding.mediaSourceChipGroup.addView(chip)
|
||||
if (selected == position) {
|
||||
selected()
|
||||
select = chip
|
||||
}
|
||||
}
|
||||
if (select != null)
|
||||
binding.animeWatchChipScroll.apply {
|
||||
binding.mediaWatchChipScroll.apply {
|
||||
post {
|
||||
scrollTo(
|
||||
(select.left - screenWidth / 2) + (select.width / 2),
|
||||
|
@ -436,7 +421,7 @@ class MangaReadAdapter(
|
|||
}
|
||||
|
||||
fun clearChips() {
|
||||
_binding?.animeSourceChipGroup?.removeAllViews()
|
||||
_binding?.mediaSourceChipGroup?.removeAllViews()
|
||||
}
|
||||
|
||||
fun handleChapters() {
|
||||
|
@ -462,70 +447,86 @@ class MangaReadAdapter(
|
|||
}
|
||||
if (formattedChapters.contains(continueEp)) {
|
||||
continueEp = chapters[formattedChapters.indexOf(continueEp)]
|
||||
binding.animeSourceContinue.visibility = View.VISIBLE
|
||||
binding.sourceContinue.visibility = View.VISIBLE
|
||||
handleProgress(
|
||||
binding.itemEpisodeProgressCont,
|
||||
binding.itemEpisodeProgress,
|
||||
binding.itemEpisodeProgressEmpty,
|
||||
binding.itemMediaProgressCont,
|
||||
binding.itemMediaProgress,
|
||||
binding.itemMediaProgressEmpty,
|
||||
media.id,
|
||||
continueEp
|
||||
)
|
||||
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight > 0.8f) {
|
||||
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight > 0.8f) {
|
||||
val e = chapters.indexOf(continueEp)
|
||||
if (e != -1 && e + 1 < chapters.size) {
|
||||
continueEp = chapters[e + 1]
|
||||
}
|
||||
}
|
||||
val ep = media.manga.chapters!![continueEp]!!
|
||||
binding.itemEpisodeImage.loadImage(media.banner ?: media.cover)
|
||||
binding.animeSourceContinueText.text =
|
||||
binding.itemMediaImage.loadImage(media.banner ?: media.cover)
|
||||
binding.mediaSourceContinueText.text =
|
||||
currActivity()!!.getString(
|
||||
R.string.continue_chapter,
|
||||
ep.number,
|
||||
if (!ep.title.isNullOrEmpty()) ep.title else ""
|
||||
)
|
||||
binding.animeSourceContinue.setOnClickListener {
|
||||
binding.sourceContinue.setOnClickListener {
|
||||
fragment.onMangaChapterClick(continueEp)
|
||||
}
|
||||
if (fragment.continueEp) {
|
||||
if ((binding.itemEpisodeProgress.layoutParams as LinearLayout.LayoutParams).weight < 0.8f) {
|
||||
binding.animeSourceContinue.performClick()
|
||||
if ((binding.itemMediaProgress.layoutParams as LinearLayout.LayoutParams).weight < 0.8f) {
|
||||
binding.sourceContinue.performClick()
|
||||
fragment.continueEp = false
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
}
|
||||
binding.animeSourceProgressBar.visibility = View.GONE
|
||||
val sourceFound = media.manga.chapters!!.isNotEmpty()
|
||||
binding.animeSourceNotFound.isGone = sourceFound
|
||||
|
||||
binding.sourceProgressBar.visibility = View.GONE
|
||||
|
||||
val sourceFound = filteredChapters.isNotEmpty()
|
||||
val isDownloadedSource = mangaReadSources[media.selected!!.sourceIndex] is OfflineMangaParser
|
||||
|
||||
if (isDownloadedSource) {
|
||||
binding.sourceNotFound.text = if (sourceFound) {
|
||||
currActivity()!!.getString(R.string.source_not_found)
|
||||
} else {
|
||||
currActivity()!!.getString(R.string.download_not_found)
|
||||
}
|
||||
} else {
|
||||
binding.sourceNotFound.text = currActivity()!!.getString(R.string.source_not_found)
|
||||
}
|
||||
|
||||
binding.sourceNotFound.isGone = sourceFound
|
||||
binding.faqbutton.isGone = sourceFound
|
||||
|
||||
|
||||
if (!sourceFound && PrefManager.getVal(PrefName.SearchSources)) {
|
||||
if (binding.animeSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
if (binding.mediaSource.adapter.count > media.selected!!.sourceIndex + 1) {
|
||||
val nextIndex = media.selected!!.sourceIndex + 1
|
||||
binding.animeSource.setText(
|
||||
binding.animeSource.adapter
|
||||
binding.mediaSource.setText(
|
||||
binding.mediaSource.adapter
|
||||
.getItem(nextIndex).toString(), false
|
||||
)
|
||||
fragment.onSourceChange(nextIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
binding.mediaSourceTitle.text = showUserText
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
{ MainScope().launch { binding.mediaSourceTitle.text = it } }
|
||||
setLanguageList(0, nextIndex)
|
||||
}
|
||||
subscribeButton(false)
|
||||
// invalidate if it's the last source
|
||||
// Invalidate if it's the last source
|
||||
val invalidate = nextIndex == mangaReadSources.names.size - 1
|
||||
fragment.loadChapters(nextIndex, invalidate)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.animeSourceContinue.visibility = View.GONE
|
||||
binding.animeSourceNotFound.visibility = View.GONE
|
||||
binding.sourceContinue.visibility = View.GONE
|
||||
binding.sourceNotFound.visibility = View.GONE
|
||||
binding.faqbutton.visibility = View.GONE
|
||||
clearChips()
|
||||
binding.animeSourceProgressBar.visibility = View.VISIBLE
|
||||
binding.sourceProgressBar.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -539,9 +540,9 @@ class MangaReadAdapter(
|
|||
ext.sourceLanguage = lang
|
||||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
binding?.mediaSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(
|
||||
binding?.mediaSourceLanguage?.setText(
|
||||
parser.extension.sources.firstOrNull()?.lang ?: "Unknown"
|
||||
)
|
||||
}
|
||||
|
@ -551,9 +552,9 @@ class MangaReadAdapter(
|
|||
parser.extension.sources.map { LanguageMapper.getLanguageName(it.lang) }
|
||||
)
|
||||
val items = adapter.count
|
||||
binding?.animeSourceLanguageContainer?.isVisible = items > 1
|
||||
binding?.mediaSourceLanguageContainer?.isVisible = items > 1
|
||||
|
||||
binding?.animeSourceLanguage?.setAdapter(adapter)
|
||||
binding?.mediaSourceLanguage?.setAdapter(adapter)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -561,7 +562,7 @@ class MangaReadAdapter(
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) :
|
||||
inner class ViewHolder(val binding: ItemMediaSourceBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package ani.dantotsu.media.manga
|
|||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
@ -31,7 +30,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.DownloadsManager.Companion.compareName
|
||||
|
@ -60,6 +59,7 @@ import ani.dantotsu.settings.saving.PrefName
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.accessAlertDialog
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.hasDirAccess
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
|
@ -74,7 +74,7 @@ import kotlin.math.max
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||
private var _binding: FragmentAnimeWatchBinding? = null
|
||||
private var _binding: FragmentMediaSourceBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
||||
|
@ -101,7 +101,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentAnimeWatchBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentMediaSourceBinding.inflate(inflater, container, false)
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
binding.mediaSourceRecycler.updatePadding(bottom = binding.mediaSourceRecycler.paddingBottom + navBarHeight)
|
||||
screenWidth = resources.displayMetrics.widthPixels.dp
|
||||
|
||||
var maxGridSize = (screenWidth / 100f).roundToInt()
|
||||
|
@ -144,13 +144,13 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
}
|
||||
|
||||
binding.animeSourceRecycler.layoutManager = gridLayoutManager
|
||||
binding.mediaSourceRecycler.layoutManager = gridLayoutManager
|
||||
|
||||
binding.ScrollTop.setOnClickListener {
|
||||
binding.animeSourceRecycler.scrollToPosition(10)
|
||||
binding.animeSourceRecycler.smoothScrollToPosition(0)
|
||||
binding.mediaSourceRecycler.scrollToPosition(10)
|
||||
binding.mediaSourceRecycler.smoothScrollToPosition(0)
|
||||
}
|
||||
binding.animeSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
binding.mediaSourceRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
||||
|
@ -164,7 +164,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
})
|
||||
model.scrolledToTop.observe(viewLifecycleOwner) {
|
||||
if (it) binding.animeSourceRecycler.scrollToPosition(0)
|
||||
if (it) binding.mediaSourceRecycler.scrollToPosition(0)
|
||||
}
|
||||
|
||||
continueEp = model.continueMedia ?: false
|
||||
|
@ -199,7 +199,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
}
|
||||
|
||||
binding.animeSourceRecycler.adapter =
|
||||
binding.mediaSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, chapterAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -214,8 +214,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
reload()
|
||||
}
|
||||
} else {
|
||||
binding.animeNotSupported.visibility = View.VISIBLE
|
||||
binding.animeNotSupported.text =
|
||||
binding.mediaNotSupported.visibility = View.VISIBLE
|
||||
binding.mediaNotSupported.text =
|
||||
getString(R.string.not_supported, media.format ?: "")
|
||||
}
|
||||
}
|
||||
|
@ -231,10 +231,10 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
|
||||
fun multiDownload(n: Int) {
|
||||
//get last viewed chapter
|
||||
// Get last viewed chapter
|
||||
val selected = media.userProgress
|
||||
val chapters = media.manga?.chapters?.values?.toList()
|
||||
//filter by selected language
|
||||
// Filter by selected language
|
||||
val progressChapterIndex = (chapters?.indexOfFirst {
|
||||
MediaNameAdapter.findChapterNumber(it.number)?.toInt() == selected
|
||||
} ?: 0) + 1
|
||||
|
@ -244,7 +244,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
// Calculate the end index
|
||||
val endIndex = minOf(progressChapterIndex + n, chapters.size)
|
||||
|
||||
//make sure there are enough chapters
|
||||
// Make sure there are enough chapters
|
||||
val chaptersToDownload = chapters.subList(progressChapterIndex, endIndex)
|
||||
|
||||
|
||||
|
@ -386,32 +386,30 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
if (allSettings.size > 1) {
|
||||
val names =
|
||||
allSettings.map { LanguageMapper.getLanguageName(it.lang) }.toTypedArray()
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, -1) { dialog, which ->
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names) { which ->
|
||||
selectedSetting = allSettings[which]
|
||||
itemSelected = true
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
val fragment =
|
||||
MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss{
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
|
@ -584,7 +582,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest chapter for subscription
|
||||
// Find latest chapter for subscription
|
||||
selected.latest =
|
||||
media.manga?.chapters?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
|
@ -618,14 +616,14 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
binding.animeSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
binding.mediaSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
|
||||
requireActivity().setNavigationTheme()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
state = binding.animeSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
state = binding.mediaSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -83,6 +83,7 @@ import ani.dantotsu.showSystemBarsRetractView
|
|||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.tryWith
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
|
@ -1013,28 +1014,27 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
PrefManager.setCustomVal("${media.id}_progressDialog", !isChecked)
|
||||
showProgressDialog = !isChecked
|
||||
}
|
||||
AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.title_update_progress))
|
||||
.setView(dialogView)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(getString(R.string.yes)) { dialog, _ ->
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.title_update_progress)
|
||||
setCustomView(dialogView)
|
||||
setCancelable(false)
|
||||
setPosButton(R.string.yes) {
|
||||
PrefManager.setCustomVal("${media.id}_save_progress", true)
|
||||
updateProgress(
|
||||
media,
|
||||
MediaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
.toString()
|
||||
)
|
||||
dialog.dismiss()
|
||||
runnable.run()
|
||||
}
|
||||
.setNegativeButton(getString(R.string.no)) { dialog, _ ->
|
||||
setNegButton(R.string.no) {
|
||||
PrefManager.setCustomVal("${media.id}_save_progress", false)
|
||||
dialog.dismiss()
|
||||
runnable.run()
|
||||
}
|
||||
.setOnCancelListener { hideSystemBars() }
|
||||
.create()
|
||||
.show()
|
||||
setOnCancelListener { hideSystemBars() }
|
||||
show()
|
||||
|
||||
}
|
||||
} else {
|
||||
if (!incognito && PrefManager.getCustomVal(
|
||||
"${media.id}_save_progress",
|
||||
|
|
|
@ -50,16 +50,16 @@ class NovelReadAdapter(
|
|||
val source =
|
||||
media.selected!!.sourceIndex.let { if (it >= novelReadSources.names.size) 0 else it }
|
||||
if (novelReadSources.names.isNotEmpty() && source in 0 until novelReadSources.names.size) {
|
||||
binding.animeSource.setText(novelReadSources.names[source], false)
|
||||
binding.mediaSource.setText(novelReadSources.names[source], false)
|
||||
}
|
||||
binding.animeSource.setAdapter(
|
||||
binding.mediaSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
novelReadSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
binding.mediaSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i)
|
||||
search()
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import androidx.recyclerview.widget.ConcatAdapter
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.FragmentMediaSourceBinding
|
||||
import ani.dantotsu.download.DownloadedType
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.novel.NovelDownloaderService
|
||||
|
@ -47,7 +47,7 @@ class NovelReadFragment : Fragment(),
|
|||
DownloadTriggerCallback,
|
||||
DownloadedCheckCallback {
|
||||
|
||||
private var _binding: FragmentAnimeWatchBinding? = null
|
||||
private var _binding: FragmentMediaSourceBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
||||
|
@ -214,11 +214,11 @@ class NovelReadFragment : Fragment(),
|
|||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
binding.mediaSourceRecycler.updatePadding(bottom = binding.mediaSourceRecycler.paddingBottom + navBarHeight)
|
||||
|
||||
binding.animeSourceRecycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.mediaSourceRecycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
model.scrolledToTop.observe(viewLifecycleOwner) {
|
||||
if (it) binding.animeSourceRecycler.scrollToPosition(0)
|
||||
if (it) binding.mediaSourceRecycler.scrollToPosition(0)
|
||||
}
|
||||
|
||||
continueEp = model.continueMedia ?: false
|
||||
|
@ -237,7 +237,7 @@ class NovelReadFragment : Fragment(),
|
|||
this,
|
||||
this
|
||||
) // probably a better way to do this but it works
|
||||
binding.animeSourceRecycler.adapter =
|
||||
binding.mediaSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, novelResponseAdapter)
|
||||
loaded = true
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
|
@ -290,7 +290,7 @@ class NovelReadFragment : Fragment(),
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
_binding = FragmentAnimeWatchBinding.inflate(inflater, container, false)
|
||||
_binding = FragmentMediaSourceBinding.inflate(inflater, container, false)
|
||||
return _binding?.root
|
||||
}
|
||||
|
||||
|
@ -304,12 +304,12 @@ class NovelReadFragment : Fragment(),
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
binding.animeSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
binding.mediaSourceRecycler.layoutManager?.onRestoreInstanceState(state)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
state = binding.animeSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
state = binding.mediaSourceRecycler.layoutManager?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -13,6 +13,7 @@ import ani.dantotsu.parsers.ShowResponse
|
|||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
|
||||
|
@ -38,7 +39,7 @@ class NovelResponseAdapter(
|
|||
val binding = holder.binding
|
||||
val novel = list[position]
|
||||
setAnimation(fragment.requireContext(), holder.binding.root)
|
||||
binding.itemEpisodeImage.loadImage(novel.coverUrl, 400, 0)
|
||||
binding.itemMediaImage.loadImage(novel.coverUrl, 400, 0)
|
||||
|
||||
val color =fragment.requireContext().getThemeColor(com.google.android.material.R.attr.colorOnBackground)
|
||||
binding.itemEpisodeTitle.text = novel.name
|
||||
|
@ -93,27 +94,22 @@ class NovelResponseAdapter(
|
|||
}
|
||||
|
||||
binding.root.setOnLongClickListener {
|
||||
val builder = androidx.appcompat.app.AlertDialog.Builder(
|
||||
fragment.requireContext(),
|
||||
R.style.MyPopup
|
||||
)
|
||||
builder.setTitle("Delete ${novel.name}?")
|
||||
builder.setMessage("Are you sure you want to delete ${novel.name}?")
|
||||
builder.setPositiveButton("Yes") { _, _ ->
|
||||
downloadedCheckCallback.deleteDownload(novel)
|
||||
deleteDownload(novel.link)
|
||||
snackString("Deleted ${novel.name}")
|
||||
if (binding.itemEpisodeFiller.text.toString()
|
||||
.contains("Download", ignoreCase = true)
|
||||
) {
|
||||
binding.itemEpisodeFiller.text = ""
|
||||
it.context.customAlertDialog().apply {
|
||||
setTitle("Delete ${novel.name}?")
|
||||
setMessage("Are you sure you want to delete ${novel.name}?")
|
||||
setPosButton(R.string.yes) {
|
||||
downloadedCheckCallback.deleteDownload(novel)
|
||||
deleteDownload(novel.link)
|
||||
snackString("Deleted ${novel.name}")
|
||||
if (binding.itemEpisodeFiller.text.toString()
|
||||
.contains("Download", ignoreCase = true)
|
||||
) {
|
||||
binding.itemEpisodeFiller.text = ""
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.no)
|
||||
show()
|
||||
}
|
||||
builder.setNegativeButton("No") { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ class ListActivity : AppCompatActivity() {
|
|||
|
||||
window.statusBarColor = primaryColor
|
||||
window.navigationBarColor = primaryColor
|
||||
binding.listed.visibility = View.GONE
|
||||
binding.listTabLayout.setBackgroundColor(primaryColor)
|
||||
binding.listAppBar.setBackgroundColor(primaryColor)
|
||||
binding.listTitle.setTextColor(primaryTextColor)
|
||||
|
|
|
@ -39,7 +39,7 @@ object AnimeSources : WatchSources() {
|
|||
}
|
||||
|
||||
fun performReorderAnimeSources() {
|
||||
//remove the downloaded source from the list to avoid duplicates
|
||||
// Remove the downloaded source from the list to avoid duplicates
|
||||
list = list.filter { it.name != "Downloaded" }
|
||||
list = sortPinnedAnimeSources(list, pinnedAnimeSources) + Lazier(
|
||||
{ OfflineAnimeParser() },
|
||||
|
|
|
@ -38,7 +38,6 @@ import ani.dantotsu.snackString
|
|||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
|
@ -19,8 +19,7 @@ import ani.dantotsu.databinding.FragmentFeedBinding
|
|||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.setBaseline
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import eu.kanade.tachiyomi.util.system.getSerializableCompat
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -44,30 +43,16 @@ class ActivityFragment : Fragment() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
type = arguments?.getSerializableCompat<ActivityType>("type") as ActivityType
|
||||
userId = arguments?.getInt("userId")
|
||||
activityId = arguments?.getInt("activityId")
|
||||
binding.titleBar.visibility = if (type == ActivityType.OTHER_USER) View.VISIBLE else View.GONE
|
||||
binding.titleText.text = if (userId == Anilist.userid) getString(R.string.create_new_activity) else getString(R.string.write_a_message)
|
||||
binding.titleImage.setOnClickListener {
|
||||
if(userId == Anilist.userid) {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(),
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
.putExtra("type", "activity"),
|
||||
null
|
||||
)
|
||||
} else{
|
||||
ContextCompat.startActivity(
|
||||
requireContext(),
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
.putExtra("type", "message")
|
||||
.putExtra("userId", userId),
|
||||
|
||||
null
|
||||
)
|
||||
}
|
||||
arguments?.let {
|
||||
type = it.getSerializableCompat<ActivityType>("type") as ActivityType
|
||||
userId = it.getInt("userId")
|
||||
activityId = it.getInt("activityId")
|
||||
}
|
||||
binding.titleBar.visibility =
|
||||
if (type == ActivityType.OTHER_USER) View.VISIBLE else View.GONE
|
||||
binding.titleText.text =
|
||||
if (userId == Anilist.userid) getString(R.string.create_new_activity) else getString(R.string.write_a_message)
|
||||
binding.titleImage.setOnClickListener { handleTitleImageClick() }
|
||||
binding.listRecyclerView.adapter = adapter
|
||||
binding.listRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
binding.listProgressBar.isVisible = true
|
||||
|
@ -106,6 +91,13 @@ class ActivityFragment : Fragment() {
|
|||
})
|
||||
}
|
||||
|
||||
private fun handleTitleImageClick() {
|
||||
val intent = Intent(context, ActivityMarkdownCreator::class.java).apply {
|
||||
putExtra("type", if (userId == Anilist.userid) "activity" else "message")
|
||||
putExtra("userId", userId)
|
||||
}
|
||||
ContextCompat.startActivity(requireContext(), intent, null)
|
||||
}
|
||||
|
||||
private suspend fun getList() {
|
||||
val list = when (type) {
|
||||
|
@ -114,14 +106,14 @@ class ActivityFragment : Fragment() {
|
|||
ActivityType.OTHER_USER -> getActivities(userId = userId)
|
||||
ActivityType.ONE -> getActivities(activityId = activityId)
|
||||
}
|
||||
adapter.addAll(list.map { ActivityItem(it, ::onActivityClick, adapter ,requireActivity()) })
|
||||
adapter.addAll(list.map { ActivityItem(it, adapter, ::onActivityClick) })
|
||||
}
|
||||
|
||||
private suspend fun getActivities(
|
||||
global: Boolean = false,
|
||||
userId: Int? = null,
|
||||
activityId: Int? = null,
|
||||
filter:Boolean = false
|
||||
filter: Boolean = false
|
||||
): List<Activity> {
|
||||
val res = Anilist.query.getFeed(userId, global, page, activityId)?.data?.page?.activities
|
||||
page += 1
|
||||
|
@ -142,37 +134,33 @@ class ActivityFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun onActivityClick(id: Int, type: String) {
|
||||
when (type) {
|
||||
"USER" -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), ProfileActivity::class.java)
|
||||
.putExtra("userId", id), null
|
||||
)
|
||||
}
|
||||
val intent = when (type) {
|
||||
"USER" -> Intent(requireContext(), ProfileActivity::class.java).putExtra("userId", id)
|
||||
"MEDIA" -> Intent(
|
||||
requireContext(),
|
||||
MediaDetailsActivity::class.java
|
||||
).putExtra("mediaId", id)
|
||||
|
||||
"MEDIA" -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), MediaDetailsActivity::class.java)
|
||||
.putExtra("mediaId", id), null
|
||||
)
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
ContextCompat.startActivity(requireContext(), intent, null)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (this::binding.isInitialized) {
|
||||
binding.root.requestLayout()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
enum class ActivityType {
|
||||
GLOBAL, USER, OTHER_USER, ONE
|
||||
}
|
||||
enum class ActivityType { GLOBAL, USER, OTHER_USER, ONE }
|
||||
|
||||
fun newInstance(type: ActivityType, userId: Int? = null, activityId: Int? = null): ActivityFragment {
|
||||
fun newInstance(
|
||||
type: ActivityType,
|
||||
userId: Int? = null,
|
||||
activityId: Int? = null
|
||||
): ActivityFragment {
|
||||
return ActivityFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable("type", type)
|
||||
|
|
|
@ -5,21 +5,19 @@ import android.view.View
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.blurImage
|
||||
import ani.dantotsu.buildMarkwon
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.api.Activity
|
||||
import ani.dantotsu.databinding.ItemActivityBinding
|
||||
import ani.dantotsu.home.status.RepliesBottomDialog
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.profile.User
|
||||
import ani.dantotsu.profile.UsersDialogFragment
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -30,9 +28,8 @@ import kotlinx.coroutines.withContext
|
|||
|
||||
class ActivityItem(
|
||||
private val activity: Activity,
|
||||
val clickCallback: (Int, type: String) -> Unit,
|
||||
private val parentAdapter: GroupieAdapter,
|
||||
private val fragActivity: FragmentActivity
|
||||
val clickCallback: (Int, type: String) -> Unit,
|
||||
) : BindableItem<ItemActivityBinding>() {
|
||||
private lateinit var binding: ItemActivityBinding
|
||||
|
||||
|
@ -55,14 +52,14 @@ class ActivityItem(
|
|||
}
|
||||
binding.activityRepliesContainer.setOnClickListener {
|
||||
RepliesBottomDialog.newInstance(activity.id)
|
||||
.show(fragActivity.supportFragmentManager, "replies")
|
||||
.show((context as FragmentActivity).supportFragmentManager, "replies")
|
||||
}
|
||||
binding.replyCount.text = activity.replyCount.toString()
|
||||
binding.activityReplies.setColorFilter(ContextCompat.getColor(binding.root.context, R.color.bg_opp))
|
||||
binding.activityLikeContainer.setOnLongClickListener {
|
||||
UsersDialogFragment().apply {
|
||||
userList(userList)
|
||||
show(fragActivity.supportFragmentManager, "dialog")
|
||||
show((context as FragmentActivity).supportFragmentManager, "dialog")
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -152,7 +149,7 @@ class ActivityItem(
|
|||
binding.activityEdit.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "activity")
|
||||
.putExtra("other", activity.text)
|
||||
.putExtra("edit", activity.id),
|
||||
|
@ -183,7 +180,7 @@ class ActivityItem(
|
|||
binding.activityEdit.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "message")
|
||||
.putExtra("other", activity.message)
|
||||
.putExtra("edit", activity.id)
|
||||
|
|
|
@ -15,7 +15,7 @@ import ani.dantotsu.profile.User
|
|||
import ani.dantotsu.profile.UsersDialogFragment
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.AniMarkdown.Companion.getBasicAniHTML
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -81,7 +81,7 @@ class ActivityReplyItem(
|
|||
binding.activityReply.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "replyActivity")
|
||||
.putExtra("parentId", parentId)
|
||||
.putExtra("other", "@${reply.user.name} "),
|
||||
|
@ -92,7 +92,7 @@ class ActivityReplyItem(
|
|||
binding.activityEdit.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "replyActivity")
|
||||
.putExtra("parentId", parentId)
|
||||
.putExtra("other", reply.text)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package ani.dantotsu.home.status
|
||||
package ani.dantotsu.profile.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
|
@ -14,12 +14,10 @@ import ani.dantotsu.connections.anilist.Anilist
|
|||
import ani.dantotsu.connections.anilist.api.ActivityReply
|
||||
import ani.dantotsu.databinding.BottomSheetRecyclerBinding
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.profile.activity.ActivityReplyItem
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.MarkdownCreatorActivity
|
||||
import ani.dantotsu.util.ActivityMarkdownCreator
|
||||
import com.xwray.groupie.GroupieAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
@ -50,7 +48,7 @@ class RepliesBottomDialog : BottomSheetDialogFragment() {
|
|||
binding.replyButton.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
context,
|
||||
Intent(context, MarkdownCreatorActivity::class.java)
|
||||
Intent(context, ActivityMarkdownCreator::class.java)
|
||||
.putExtra("type", "replyActivity")
|
||||
.putExtra("parentId", activityId),
|
||||
null
|
||||
|
@ -73,14 +71,10 @@ class RepliesBottomDialog : BottomSheetDialogFragment() {
|
|||
adapter.update(
|
||||
replies.map {
|
||||
ActivityReplyItem(
|
||||
it,
|
||||
activityId,
|
||||
requireActivity(),
|
||||
adapter,
|
||||
clickCallback = { int, _ ->
|
||||
onClick(int)
|
||||
}
|
||||
)
|
||||
it, activityId, requireActivity(), adapter,
|
||||
) { i, _ ->
|
||||
onClick(i)
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
|
@ -20,7 +20,7 @@ import ani.dantotsu.profile.notification.NotificationFragment.Companion.Notifica
|
|||
import nl.joery.animatedbottombar.AnimatedBottomBar
|
||||
|
||||
class NotificationActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityNotificationBinding
|
||||
lateinit var binding: ActivityNotificationBinding
|
||||
private var selected: Int = 0
|
||||
lateinit var navBar: AnimatedBottomBar
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -38,8 +38,8 @@ class NotificationActivity : AppCompatActivity() {
|
|||
bottomMargin = navBarHeight
|
||||
}
|
||||
val tabs = listOf(
|
||||
Pair(R.drawable.ic_round_movie_filter_24, "Media"),
|
||||
Pair(R.drawable.ic_round_person_24, "User"),
|
||||
Pair(R.drawable.ic_round_movie_filter_24, "Media"),
|
||||
Pair(R.drawable.ic_round_notifications_active_24, "Subs"),
|
||||
Pair(R.drawable.ic_round_comment_24, "Comments")
|
||||
)
|
||||
|
@ -49,7 +49,6 @@ class NotificationActivity : AppCompatActivity() {
|
|||
val getOne = intent.getIntExtra("activityId", -1)
|
||||
if (getOne != -1) navBar.isVisible = false
|
||||
binding.notificationViewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle, getOne)
|
||||
binding.notificationViewPager.setOffscreenPageLimit(4)
|
||||
binding.notificationViewPager.setCurrentItem(selected, false)
|
||||
navBar.selectTabAt(selected)
|
||||
navBar.setOnTabSelectListener(object : AnimatedBottomBar.OnTabSelectListener {
|
||||
|
@ -84,8 +83,8 @@ class NotificationActivity : AppCompatActivity() {
|
|||
override fun getItemCount(): Int = if (id != -1) 1 else 4
|
||||
|
||||
override fun createFragment(position: Int): Fragment = when (position) {
|
||||
0 -> NotificationFragment.newInstance(if (id != -1) NotificationType.ONE else NotificationType.MEDIA, id)
|
||||
1 -> NotificationFragment.newInstance(NotificationType.USER)
|
||||
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)
|
||||
|
|
|
@ -46,8 +46,10 @@ class NotificationFragment : Fragment() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
type = arguments?.getSerializableCompat<NotificationType>("type") as NotificationType
|
||||
getID = arguments?.getInt("id") ?: -1
|
||||
arguments?.let {
|
||||
getID = it.getInt("id")
|
||||
type = it.getSerializableCompat<NotificationType>("type") as NotificationType
|
||||
}
|
||||
binding.notificationRecyclerView.adapter = adapter
|
||||
binding.notificationRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
binding.notificationProgressBar.isVisible = true
|
||||
|
@ -158,47 +160,31 @@ class NotificationFragment : Fragment() {
|
|||
!binding.notificationRecyclerView.canScrollVertically(1)
|
||||
}
|
||||
|
||||
fun onClick(
|
||||
id: Int,
|
||||
optional: Int?,
|
||||
type: NotificationClickType
|
||||
) {
|
||||
when (type) {
|
||||
NotificationClickType.USER -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), ProfileActivity::class.java)
|
||||
.putExtra("userId", id), null
|
||||
)
|
||||
fun onClick(id: Int, optional: Int?, type: NotificationClickType) {
|
||||
val intent = when (type) {
|
||||
NotificationClickType.USER -> Intent(requireContext(), ProfileActivity::class.java).apply {
|
||||
putExtra("userId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.MEDIA -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), MediaDetailsActivity::class.java)
|
||||
.putExtra("mediaId", id), null
|
||||
)
|
||||
NotificationClickType.MEDIA -> Intent(requireContext(), MediaDetailsActivity::class.java).apply {
|
||||
putExtra("mediaId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.ACTIVITY -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), FeedActivity::class.java)
|
||||
.putExtra("activityId", id), null
|
||||
)
|
||||
NotificationClickType.ACTIVITY -> Intent(requireContext(), FeedActivity::class.java).apply {
|
||||
putExtra("activityId", id)
|
||||
}
|
||||
|
||||
NotificationClickType.COMMENT -> {
|
||||
ContextCompat.startActivity(
|
||||
requireContext(), Intent(requireContext(), MediaDetailsActivity::class.java)
|
||||
.putExtra("FRAGMENT_TO_LOAD", "COMMENTS")
|
||||
.putExtra("mediaId", id)
|
||||
.putExtra("commentId", optional ?: -1),
|
||||
null
|
||||
)
|
||||
|
||||
NotificationClickType.COMMENT -> Intent(requireContext(), MediaDetailsActivity::class.java).apply {
|
||||
putExtra("FRAGMENT_TO_LOAD", "COMMENTS")
|
||||
putExtra("mediaId", id)
|
||||
putExtra("commentId", optional ?: -1)
|
||||
}
|
||||
|
||||
NotificationClickType.UNDEFINED -> {
|
||||
// Do nothing
|
||||
}
|
||||
NotificationClickType.UNDEFINED -> null
|
||||
}
|
||||
|
||||
intent?.let {
|
||||
ContextCompat.startActivity(requireContext(), it, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,18 +192,12 @@ class NotificationFragment : Fragment() {
|
|||
super.onResume()
|
||||
if (this::binding.isInitialized) {
|
||||
binding.root.requestLayout()
|
||||
binding.root.setBaseline((activity as NotificationActivity).navBar)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
enum class NotificationClickType {
|
||||
USER, MEDIA, ACTIVITY, COMMENT, UNDEFINED
|
||||
}
|
||||
|
||||
enum class NotificationType {
|
||||
MEDIA, USER, SUBSCRIPTION, COMMENT, ONE
|
||||
}
|
||||
enum class NotificationClickType { USER, MEDIA, ACTIVITY, COMMENT, UNDEFINED }
|
||||
enum class NotificationType { MEDIA, USER, SUBSCRIPTION, COMMENT, ONE }
|
||||
|
||||
fun newInstance(type: NotificationType, id: Int = -1): NotificationFragment {
|
||||
return NotificationFragment().apply {
|
||||
|
|
|
@ -35,6 +35,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
|
@ -178,25 +179,20 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
entry.name.lowercase().replace("_", " ")
|
||||
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() }
|
||||
}.toTypedArray()
|
||||
val builder = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
val listOrder: String = PrefManager.getVal(PrefName.LangSort)
|
||||
val index = LanguageMapper.Companion.Language.entries.toTypedArray()
|
||||
.indexOfFirst { it.code == listOrder }
|
||||
builder.setTitle("Language")
|
||||
builder.setSingleChoiceItems(languageOptions, index) { dialog, i ->
|
||||
PrefManager.setVal(
|
||||
PrefName.LangSort,
|
||||
LanguageMapper.Companion.Language.entries[i].code
|
||||
)
|
||||
val currentFragment =
|
||||
supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
|
||||
if (currentFragment is SearchQueryHandler) {
|
||||
currentFragment.notifyDataChanged()
|
||||
customAlertDialog().apply {
|
||||
setTitle("Language")
|
||||
singleChoiceItems(languageOptions, index) { selected ->
|
||||
PrefManager.setVal(PrefName.LangSort, LanguageMapper.Companion.Language.entries[selected].code)
|
||||
val currentFragment = supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
|
||||
if (currentFragment is SearchQueryHandler) {
|
||||
currentFragment.notifyDataChanged()
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
show()
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
binding.settingsContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = statusBarHeight
|
||||
|
@ -247,10 +243,10 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
)
|
||||
view.repositoryItem.text = item.removePrefix("https://raw.githubusercontent.com")
|
||||
view.repositoryItem.setOnClickListener {
|
||||
AlertDialog.Builder(this@ExtensionsActivity, R.style.MyPopup)
|
||||
.setTitle(R.string.rem_repository)
|
||||
.setMessage(item)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.rem_repository)
|
||||
setMessage(item)
|
||||
setPosButton(R.string.ok) {
|
||||
val repos = PrefManager.getVal<Set<String>>(prefName).minus(item)
|
||||
PrefManager.setVal(prefName, repos)
|
||||
repoInventory.removeView(view.root)
|
||||
|
@ -267,13 +263,10 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
else -> {}
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
.show()
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
view.repositoryItem.setOnLongClickListener {
|
||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
|
@ -324,20 +317,18 @@ class ExtensionsActivity : AppCompatActivity() {
|
|||
dialogView.repoInventory.apply {
|
||||
getSavedRepositories(this, type)
|
||||
}
|
||||
val alertDialog = AlertDialog.Builder(this@ExtensionsActivity, R.style.MyPopup)
|
||||
.setTitle(R.string.edit_repositories)
|
||||
.setView(dialogView.root)
|
||||
.setPositiveButton(getString(R.string.add)) { _, _ ->
|
||||
if (!dialogView.repositoryTextBox.text.isNullOrBlank())
|
||||
processUserInput(dialogView.repositoryTextBox.text.toString(), type)
|
||||
}
|
||||
.setNegativeButton(getString(R.string.close)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
processEditorAction(dialogView.repositoryTextBox, type)
|
||||
alertDialog.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.edit_repositories)
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.add) {
|
||||
if (!dialogView.repositoryTextBox.text.isNullOrBlank()) {
|
||||
processUserInput(dialogView.repositoryTextBox.text.toString(), type)
|
||||
}
|
||||
}
|
||||
setNegButton(R.string.close)
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,11 @@ class FAQActivity : AppCompatActivity() {
|
|||
currContext()?.getString(R.string.question_5) ?: "",
|
||||
currContext()?.getString(R.string.answer_5) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_anilist,
|
||||
currContext()?.getString(R.string.question_18) ?: "",
|
||||
currContext()?.getString(R.string.answer_18) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_anilist,
|
||||
currContext()?.getString(R.string.question_6) ?: "",
|
||||
|
@ -60,6 +65,11 @@ class FAQActivity : AppCompatActivity() {
|
|||
currContext()?.getString(R.string.question_7) ?: "",
|
||||
currContext()?.getString(R.string.answer_7) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_round_magnet_24,
|
||||
currContext()?.getString(R.string.question_19) ?: "",
|
||||
currContext()?.getString(R.string.answer_19) ?: ""
|
||||
),
|
||||
Triple(
|
||||
R.drawable.ic_round_lock_open_24,
|
||||
currContext()?.getString(R.string.question_9) ?: "",
|
||||
|
|
|
@ -25,13 +25,15 @@ import androidx.viewpager2.widget.ViewPager2
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.databinding.FragmentExtensionsBinding
|
||||
import ani.dantotsu.others.LanguageMapper
|
||||
import ani.dantotsu.others.LanguageMapper.Companion.getLanguageName
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
|
@ -72,16 +74,15 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
if (allSettings.isNotEmpty()) {
|
||||
var selectedSetting = allSettings[0]
|
||||
if (allSettings.size > 1) {
|
||||
val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) }
|
||||
val names = allSettings.map { getLanguageName(it.lang) }
|
||||
.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { dialog, which ->
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names, selectedIndex) { which ->
|
||||
itemSelected = true
|
||||
selectedIndex = which
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
val fragment =
|
||||
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
|
@ -93,13 +94,13 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss {
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment =
|
||||
|
@ -295,7 +296,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val extension = getItem(position)
|
||||
val nsfw = if (extension.isNsfw) "(18+)" else ""
|
||||
val lang = LanguageMapper.getLanguageName(extension.lang)
|
||||
val lang = getLanguageName(extension.lang)
|
||||
holder.extensionNameTextView.text = extension.name
|
||||
val versionText = "$lang ${extension.versionName} $nsfw"
|
||||
holder.extensionVersionTextView.text = versionText
|
||||
|
|
|
@ -34,6 +34,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
|
@ -74,13 +75,12 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
val names = allSettings.map { LanguageMapper.getLanguageName(it.lang) }
|
||||
.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { dialog, which ->
|
||||
requireContext().customAlertDialog().apply {
|
||||
setTitle("Select a Source")
|
||||
singleChoiceItems(names, selectedIndex) { which ->
|
||||
itemSelected = true
|
||||
selectedIndex = which
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
val fragment =
|
||||
|
@ -93,13 +93,13 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
|||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onDismiss {
|
||||
if (!itemSelected) {
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment =
|
||||
|
|
|
@ -28,6 +28,7 @@ import ani.dantotsu.snackString
|
|||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import com.google.android.material.slider.Slider.OnChangeListener
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
@ -100,20 +101,19 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
R.string.default_playback_speed,
|
||||
speedsName[PrefManager.getVal(PrefName.DefaultSpeed)]
|
||||
)
|
||||
val speedDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.default_speed))
|
||||
binding.playerSettingsSpeed.setOnClickListener {
|
||||
val dialog =
|
||||
speedDialog.setSingleChoiceItems(
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.default_speed))
|
||||
singleChoiceItems(
|
||||
speedsName,
|
||||
PrefManager.getVal(PrefName.DefaultSpeed)
|
||||
) { dialog, i ->
|
||||
) { i ->
|
||||
PrefManager.setVal(PrefName.DefaultSpeed, i)
|
||||
binding.playerSettingsSpeed.text =
|
||||
getString(R.string.default_playback_speed, speedsName[i])
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.playerSettingsCursedSpeeds.isChecked = PrefManager.getVal(PrefName.CursedSpeeds)
|
||||
|
@ -278,17 +278,17 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
val resizeModes = arrayOf("Original", "Zoom", "Stretch")
|
||||
val resizeDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.default_resize_mode))
|
||||
binding.playerResizeMode.setOnClickListener {
|
||||
val dialog = resizeDialog.setSingleChoiceItems(
|
||||
resizeModes,
|
||||
PrefManager.getVal<Int>(PrefName.Resize)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.Resize, count)
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.default_resize_mode))
|
||||
singleChoiceItems(
|
||||
resizeModes,
|
||||
PrefManager.getVal<Int>(PrefName.Resize)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.Resize, count)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleSubOptions(isChecked: Boolean) {
|
||||
|
@ -332,18 +332,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Blue",
|
||||
"Magenta"
|
||||
)
|
||||
val primaryColorDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.primary_sub_color))
|
||||
binding.videoSubColorPrimary.setOnClickListener {
|
||||
val dialog = primaryColorDialog.setSingleChoiceItems(
|
||||
colorsPrimary,
|
||||
PrefManager.getVal(PrefName.PrimaryColor)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.PrimaryColor, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.primary_sub_color))
|
||||
singleChoiceItems(
|
||||
colorsPrimary,
|
||||
PrefManager.getVal(PrefName.PrimaryColor)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.PrimaryColor, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
val colorsSecondary = arrayOf(
|
||||
"Black",
|
||||
|
@ -359,32 +359,32 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Magenta",
|
||||
"Transparent"
|
||||
)
|
||||
val secondaryColorDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.outline_sub_color))
|
||||
binding.videoSubColorSecondary.setOnClickListener {
|
||||
val dialog = secondaryColorDialog.setSingleChoiceItems(
|
||||
colorsSecondary,
|
||||
PrefManager.getVal(PrefName.SecondaryColor)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.SecondaryColor, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.outline_sub_color))
|
||||
singleChoiceItems(
|
||||
colorsSecondary,
|
||||
PrefManager.getVal(PrefName.SecondaryColor)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.SecondaryColor, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
val typesOutline = arrayOf("Outline", "Shine", "Drop Shadow", "None")
|
||||
val outlineDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.outline_type))
|
||||
binding.videoSubOutline.setOnClickListener {
|
||||
val dialog = outlineDialog.setSingleChoiceItems(
|
||||
typesOutline,
|
||||
PrefManager.getVal(PrefName.Outline)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.Outline, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.outline_type))
|
||||
singleChoiceItems(
|
||||
typesOutline,
|
||||
PrefManager.getVal(PrefName.Outline)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.Outline, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
val colorsSubBackground = arrayOf(
|
||||
"Transparent",
|
||||
|
@ -400,18 +400,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Blue",
|
||||
"Magenta"
|
||||
)
|
||||
val subBackgroundDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.sub_background_color_select))
|
||||
binding.videoSubColorBackground.setOnClickListener {
|
||||
val dialog = subBackgroundDialog.setSingleChoiceItems(
|
||||
colorsSubBackground,
|
||||
PrefManager.getVal(PrefName.SubBackground)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.SubBackground, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.sub_background_color_select))
|
||||
singleChoiceItems(
|
||||
colorsSubBackground,
|
||||
PrefManager.getVal(PrefName.SubBackground)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.SubBackground, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
val colorsSubWindow = arrayOf(
|
||||
|
@ -428,18 +428,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Blue",
|
||||
"Magenta"
|
||||
)
|
||||
val subWindowDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.sub_window_color_select))
|
||||
binding.videoSubColorWindow.setOnClickListener {
|
||||
val dialog = subWindowDialog.setSingleChoiceItems(
|
||||
colorsSubWindow,
|
||||
PrefManager.getVal(PrefName.SubWindow)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.SubWindow, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.sub_window_color_select))
|
||||
singleChoiceItems(
|
||||
colorsSubWindow,
|
||||
PrefManager.getVal(PrefName.SubWindow)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.SubWindow, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.videoSubAlpha.value = PrefManager.getVal(PrefName.SubAlpha)
|
||||
|
@ -459,18 +459,18 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
"Levenim MT Bold",
|
||||
"Blocky"
|
||||
)
|
||||
val fontDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.subtitle_font))
|
||||
binding.videoSubFont.setOnClickListener {
|
||||
val dialog = fontDialog.setSingleChoiceItems(
|
||||
fonts,
|
||||
PrefManager.getVal(PrefName.Font)
|
||||
) { dialog, count ->
|
||||
PrefManager.setVal(PrefName.Font, count)
|
||||
dialog.dismiss()
|
||||
updateSubPreview()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.subtitle_font))
|
||||
singleChoiceItems(
|
||||
fonts,
|
||||
PrefManager.getVal(PrefName.Font)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.Font, count)
|
||||
updateSubPreview()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
binding.subtitleFontSize.setText(PrefManager.getVal<Int>(PrefName.FontSize).toString())
|
||||
binding.subtitleFontSize.setOnEditorActionListener { _, actionId, _ ->
|
||||
|
|
|
@ -20,6 +20,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.databinding.ActivitySettingsCommonBinding
|
||||
import ani.dantotsu.databinding.DialogSetPasswordBinding
|
||||
import ani.dantotsu.databinding.DialogUserAgentBinding
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.initActivity
|
||||
|
@ -37,6 +38,7 @@ import ani.dantotsu.themes.ThemeManager
|
|||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.LauncherWrapper
|
||||
import ani.dantotsu.util.StoragePermissions
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
|
@ -160,18 +162,16 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
icon = R.drawable.ic_download_24,
|
||||
onClick = {
|
||||
val managers = arrayOf("Default", "1DM", "ADM")
|
||||
val downloadManagerDialog =
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.download_manager)
|
||||
var downloadManager: Int = PrefManager.getVal(PrefName.DownloadManager)
|
||||
val dialog = downloadManagerDialog.setSingleChoiceItems(
|
||||
managers, downloadManager
|
||||
) { dialog, count ->
|
||||
downloadManager = count
|
||||
PrefManager.setVal(PrefName.DownloadManager, downloadManager)
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.download_manager))
|
||||
singleChoiceItems(
|
||||
managers,
|
||||
PrefManager.getVal(PrefName.DownloadManager)
|
||||
) { count ->
|
||||
PrefManager.setVal(PrefName.DownloadManager, count)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
|
@ -180,90 +180,67 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
desc = getString(R.string.app_lock_desc),
|
||||
icon = R.drawable.ic_round_lock_open_24,
|
||||
onClick = {
|
||||
val passwordDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.app_lock)
|
||||
.setView(R.layout.dialog_set_password)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||
val passwordInput =
|
||||
(dialog as AlertDialog).findViewById<EditText>(R.id.passwordInput)
|
||||
val confirmPasswordInput =
|
||||
dialog.findViewById<EditText>(R.id.confirmPasswordInput)
|
||||
val forgotPasswordCheckbox =
|
||||
dialog.findViewById<CheckBox>(R.id.forgotPasswordCheckbox)
|
||||
if (forgotPasswordCheckbox?.isChecked == true) {
|
||||
customAlertDialog().apply {
|
||||
val view = DialogSetPasswordBinding.inflate(layoutInflater)
|
||||
setTitle(R.string.app_lock)
|
||||
setCustomView(view.root)
|
||||
setPosButton(R.string.ok) {
|
||||
if (view.forgotPasswordCheckbox.isChecked) {
|
||||
PrefManager.setVal(PrefName.OverridePassword, true)
|
||||
}
|
||||
|
||||
val password = passwordInput?.text.toString()
|
||||
val confirmPassword = confirmPasswordInput?.text.toString()
|
||||
|
||||
val password = view.passwordInput.text.toString()
|
||||
val confirmPassword = view.confirmPasswordInput.text.toString()
|
||||
if (password == confirmPassword && password.isNotEmpty()) {
|
||||
PrefManager.setVal(PrefName.AppPassword, password)
|
||||
if (dialog.findViewById<CheckBox>(R.id.biometricCheckbox)?.isChecked == true) {
|
||||
if (view.biometricCheckbox.isChecked) {
|
||||
val canBiometricPrompt =
|
||||
BiometricManager.from(applicationContext)
|
||||
.canAuthenticate(
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK
|
||||
) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
|
||||
if (canBiometricPrompt) {
|
||||
val biometricPrompt =
|
||||
BiometricPromptUtils.createBiometricPrompt(
|
||||
this@SettingsCommonActivity
|
||||
) { _ ->
|
||||
BiometricPromptUtils.createBiometricPrompt(this@SettingsCommonActivity) { _ ->
|
||||
val token = UUID.randomUUID().toString()
|
||||
PrefManager.setVal(
|
||||
PrefName.BiometricToken,
|
||||
token
|
||||
)
|
||||
toast(R.string.success)
|
||||
dialog.dismiss()
|
||||
}
|
||||
val promptInfo =
|
||||
BiometricPromptUtils.createPromptInfo(
|
||||
this@SettingsCommonActivity
|
||||
)
|
||||
BiometricPromptUtils.createPromptInfo(this@SettingsCommonActivity)
|
||||
biometricPrompt.authenticate(promptInfo)
|
||||
}
|
||||
|
||||
} else {
|
||||
PrefManager.setVal(PrefName.BiometricToken, "")
|
||||
toast(R.string.success)
|
||||
dialog.dismiss()
|
||||
}
|
||||
} else {
|
||||
toast(R.string.password_mismatch)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.remove) { dialog, _ ->
|
||||
setNegButton(R.string.cancel)
|
||||
setNeutralButton(R.string.remove){
|
||||
PrefManager.setVal(PrefName.AppPassword, "")
|
||||
PrefManager.setVal(PrefName.BiometricToken, "")
|
||||
PrefManager.setVal(PrefName.OverridePassword, false)
|
||||
toast(R.string.success)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
|
||||
passwordDialog.window?.setDimAmount(0.8f)
|
||||
passwordDialog.setOnShowListener {
|
||||
passwordDialog.findViewById<EditText>(R.id.passwordInput)
|
||||
?.requestFocus()
|
||||
val biometricCheckbox =
|
||||
passwordDialog.findViewById<CheckBox>(R.id.biometricCheckbox)
|
||||
val forgotPasswordCheckbox =
|
||||
passwordDialog.findViewById<CheckBox>(R.id.forgotPasswordCheckbox)
|
||||
val canAuthenticate =
|
||||
BiometricManager.from(applicationContext).canAuthenticate(
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK
|
||||
) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
biometricCheckbox?.isVisible = canAuthenticate
|
||||
biometricCheckbox?.isChecked =
|
||||
PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty()
|
||||
forgotPasswordCheckbox?.isChecked =
|
||||
PrefManager.getVal(PrefName.OverridePassword)
|
||||
setOnShowListener {
|
||||
view.passwordInput.requestFocus()
|
||||
val canAuthenticate =
|
||||
BiometricManager.from(applicationContext).canAuthenticate(
|
||||
BiometricManager.Authenticators.BIOMETRIC_WEAK
|
||||
) == BiometricManager.BIOMETRIC_SUCCESS
|
||||
view.biometricCheckbox.isVisible = canAuthenticate
|
||||
view.biometricCheckbox.isChecked =
|
||||
PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty()
|
||||
view.forgotPasswordCheckbox.isChecked =
|
||||
PrefManager.getVal(PrefName.OverridePassword)
|
||||
}
|
||||
show()
|
||||
}
|
||||
passwordDialog.show()
|
||||
}
|
||||
|
||||
),
|
||||
|
@ -328,10 +305,10 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
desc = getString(R.string.change_download_location_desc),
|
||||
icon = R.drawable.ic_round_source_24,
|
||||
onClick = {
|
||||
val dialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.change_download_location)
|
||||
.setMessage(R.string.download_location_msg)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||
context.customAlertDialog().apply{
|
||||
setTitle(R.string.change_download_location)
|
||||
setMessage(R.string.download_location_msg)
|
||||
setPosButton(R.string.ok){
|
||||
val oldUri = PrefManager.getVal<String>(PrefName.DownloadsDir)
|
||||
launcher.registerForCallback { success ->
|
||||
if (success) {
|
||||
|
@ -354,12 +331,10 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
launcher.launch()
|
||||
dialog.dismiss()
|
||||
}.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
|
@ -372,6 +347,17 @@ class SettingsCommonActivity : AppCompatActivity() {
|
|||
PrefManager.setVal(PrefName.ContinueMedia, isChecked)
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
type = 2,
|
||||
name = getString(R.string.hide_private),
|
||||
desc = getString(R.string.hide_private_desc),
|
||||
icon = R.drawable.ic_round_remove_red_eye_24,
|
||||
isChecked = PrefManager.getVal(PrefName.HidePrivate),
|
||||
switch = { isChecked, _ ->
|
||||
PrefManager.setVal(PrefName.HidePrivate, isChecked)
|
||||
restartApp()
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
type = 2,
|
||||
name = getString(R.string.search_source_list),
|
||||
|
|
|
@ -81,11 +81,11 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
view.repositoryItem.text =
|
||||
item.removePrefix("https://raw.githubusercontent.com/")
|
||||
view.repositoryItem.setOnClickListener {
|
||||
AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.rem_repository).setMessage(item)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
val repos =
|
||||
PrefManager.getVal<Set<String>>(repoList).minus(item)
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.rem_repository)
|
||||
setMessage(item)
|
||||
setPosButton(R.string.ok) {
|
||||
val repos = PrefManager.getVal<Set<String>>(repoList).minus(item)
|
||||
PrefManager.setVal(repoList, repos)
|
||||
setExtensionOutput(repoInventory, type)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
|
@ -93,18 +93,16 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
MediaType.ANIME -> {
|
||||
animeExtensionManager.findAvailableExtensions()
|
||||
}
|
||||
|
||||
MediaType.MANGA -> {
|
||||
mangaExtensionManager.findAvailableExtensions()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
}.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create().show()
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
view.repositoryItem.setOnLongClickListener {
|
||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
|
@ -209,27 +207,27 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
val editText = dialogView.userAgentTextBox.apply {
|
||||
hint = getString(R.string.manga_add_repository)
|
||||
}
|
||||
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.manga_add_repository).setView(dialogView.root)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.manga_add_repository)
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.ok) {
|
||||
if (!editText.text.isNullOrBlank()) processUserInput(
|
||||
editText.text.toString(),
|
||||
MediaType.MANGA,
|
||||
it.attachView
|
||||
)
|
||||
dialog.dismiss()
|
||||
}.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create()
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
attach { dialog ->
|
||||
processEditorAction(
|
||||
dialog,
|
||||
editText,
|
||||
MediaType.MANGA,
|
||||
it.attachView
|
||||
)
|
||||
}
|
||||
}.show()
|
||||
|
||||
processEditorAction(
|
||||
alertDialog,
|
||||
editText,
|
||||
MediaType.MANGA,
|
||||
it.attachView
|
||||
)
|
||||
alertDialog.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
},
|
||||
attach = {
|
||||
setExtensionOutput(it.attachView, MediaType.MANGA)
|
||||
|
@ -258,24 +256,18 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
|||
val dialogView = DialogUserAgentBinding.inflate(layoutInflater)
|
||||
val editText = dialogView.userAgentTextBox
|
||||
editText.setText(PrefManager.getVal<String>(PrefName.DefaultUserAgent))
|
||||
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.user_agent).setView(dialogView.root)
|
||||
.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
PrefManager.setVal(
|
||||
PrefName.DefaultUserAgent,
|
||||
editText.text.toString()
|
||||
)
|
||||
dialog.dismiss()
|
||||
}.setNeutralButton(getString(R.string.reset)) { dialog, _ ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.user_agent)
|
||||
setCustomView(dialogView.root)
|
||||
setPosButton(R.string.ok) {
|
||||
PrefManager.setVal(PrefName.DefaultUserAgent, editText.text.toString())
|
||||
}
|
||||
setNeutralButton(R.string.reset) {
|
||||
PrefManager.removeVal(PrefName.DefaultUserAgent)
|
||||
editText.setText("")
|
||||
dialog.dismiss()
|
||||
}.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}.create()
|
||||
|
||||
alertDialog.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
setNegButton(R.string.cancel)
|
||||
}.show()
|
||||
}
|
||||
),
|
||||
Settings(
|
||||
|
|
|
@ -25,6 +25,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
import java.util.Locale
|
||||
|
||||
class SettingsNotificationActivity : AppCompatActivity() {
|
||||
|
@ -77,26 +78,16 @@ class SettingsNotificationActivity : AppCompatActivity() {
|
|||
desc = getString(R.string.subscriptions_info),
|
||||
icon = R.drawable.ic_round_notifications_none_24,
|
||||
onClick = {
|
||||
val speedDialog = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
.setTitle(R.string.subscriptions_checking_time)
|
||||
val dialog =
|
||||
speedDialog.setSingleChoiceItems(timeNames, curTime) { dialog, i ->
|
||||
context.customAlertDialog().apply {
|
||||
setTitle(R.string.subscriptions_checking_time)
|
||||
singleChoiceItems(timeNames, curTime) { i ->
|
||||
curTime = i
|
||||
it.settingsTitle.text =
|
||||
getString(
|
||||
R.string.subscriptions_checking_time_s,
|
||||
timeNames[i]
|
||||
)
|
||||
PrefManager.setVal(
|
||||
PrefName.SubscriptionNotificationInterval,
|
||||
curTime
|
||||
)
|
||||
dialog.dismiss()
|
||||
TaskScheduler.create(
|
||||
context, PrefManager.getVal(PrefName.UseAlarmManager)
|
||||
).scheduleAllTasks(context)
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
it.settingsTitle.text = getString(R.string.subscriptions_checking_time_s, timeNames[i])
|
||||
PrefManager.setVal(PrefName.SubscriptionNotificationInterval, curTime)
|
||||
TaskScheduler.create(context, PrefManager.getVal(PrefName.UseAlarmManager)).scheduleAllTasks(context)
|
||||
}
|
||||
show()
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
TaskScheduler.create(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import ani.dantotsu.settings.saving.PrefManager
|
|||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.util.customAlertDialog
|
||||
|
||||
class UserInterfaceSettingsActivity : AppCompatActivity() {
|
||||
lateinit var binding: ActivityUserInterfaceSettingsBinding
|
||||
|
@ -38,20 +39,23 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
|
|||
binding.uiSettingsHomeLayout.setOnClickListener {
|
||||
val set = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toMutableList()
|
||||
val views = resources.getStringArray(R.array.home_layouts)
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.home_layout_show)).apply {
|
||||
setMultiChoiceItems(
|
||||
views,
|
||||
PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toBooleanArray()
|
||||
) { _, i, value ->
|
||||
set[i] = value
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.home_layout_show))
|
||||
multiChoiceItems(
|
||||
items = views,
|
||||
checkedItems = PrefManager.getVal<List<Boolean>>(PrefName.HomeLayout).toBooleanArray()
|
||||
) { selectedItems ->
|
||||
for (i in selectedItems.indices) {
|
||||
set[i] = selectedItems[i]
|
||||
}
|
||||
setPositiveButton("Done") { _, _ ->
|
||||
PrefManager.setVal(PrefName.HomeLayout, set)
|
||||
restartApp()
|
||||
}
|
||||
}.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
}
|
||||
setPosButton(R.string.ok) {
|
||||
PrefManager.setVal(PrefName.HomeLayout, set)
|
||||
restartApp()
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
binding.uiSettingsSmallView.isChecked = PrefManager.getVal(PrefName.SmallView)
|
||||
|
|
|
@ -22,6 +22,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
|
|||
CheckUpdate(Pref(Location.General, Boolean::class, true)),
|
||||
VerboseLogging(Pref(Location.General, Boolean::class, false)),
|
||||
DohProvider(Pref(Location.General, Int::class, 0)),
|
||||
HidePrivate(Pref(Location.General, Boolean::class, false)),
|
||||
DefaultUserAgent(
|
||||
Pref(
|
||||
Location.General,
|
||||
|
|
|
@ -26,7 +26,7 @@ import io.noties.markwon.editor.MarkwonEditorTextWatcher
|
|||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
|
||||
class MarkdownCreatorActivity : AppCompatActivity() {
|
||||
class ActivityMarkdownCreator : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMarkdownCreatorBinding
|
||||
private lateinit var type: String
|
||||
private var text: String = ""
|
||||
|
@ -80,24 +80,28 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
finish()
|
||||
return
|
||||
}
|
||||
binding.markdownCreatorTitle.text = when (type) {
|
||||
"activity" -> getString(R.string.create_new_activity)
|
||||
"review" -> getString(R.string.create_new_review)
|
||||
"message" -> getString(R.string.create_new_message)
|
||||
"replyActivity" -> {
|
||||
parentId = intent.getIntExtra("parentId", -1)
|
||||
if (parentId == -1) {
|
||||
toast("Error: No parent ID")
|
||||
finish()
|
||||
return
|
||||
}
|
||||
getString(R.string.create_new_reply)
|
||||
val editId = intent.getIntExtra("edit", -1)
|
||||
val userId = intent.getIntExtra("userId", -1)
|
||||
parentId = intent.getIntExtra("parentId", -1)
|
||||
when (type) {
|
||||
"replyActivity" -> if (parentId == -1) {
|
||||
toast("Error: No parent ID")
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
else -> ""
|
||||
"message" -> {
|
||||
if (editId == -1) {
|
||||
binding.privateCheckbox.visibility = ViewGroup.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
var private = false
|
||||
binding.privateCheckbox.setOnCheckedChangeListener { _, isChecked ->
|
||||
private = isChecked
|
||||
}
|
||||
|
||||
ping = intent.getStringExtra("other")
|
||||
val userId = intent.getIntExtra("userId", -1)
|
||||
text = ping ?: ""
|
||||
binding.editText.setText(text)
|
||||
binding.editText.addTextChangedListener {
|
||||
|
@ -116,12 +120,11 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
toast(getString(R.string.cannot_be_empty))
|
||||
return@setOnClickListener
|
||||
}
|
||||
AlertDialog.Builder(this, R.style.MyPopup).apply {
|
||||
customAlertDialog().apply {
|
||||
setTitle(R.string.warning)
|
||||
setMessage(R.string.post_to_anilist_warning)
|
||||
setPositiveButton(R.string.ok) { _, _ ->
|
||||
setPosButton(R.string.ok) {
|
||||
launchIO {
|
||||
val editId = intent.getIntExtra("edit", -1)
|
||||
val isEdit = editId != -1
|
||||
val success = when (type) {
|
||||
"activity" -> if (isEdit) {
|
||||
|
@ -135,25 +138,27 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
} else {
|
||||
Anilist.mutation.postReply(parentId, text)
|
||||
}
|
||||
"message" -> if (isEdit) { //TODO private
|
||||
Anilist.mutation.postMessage(userId , text, editId)
|
||||
"message" -> if (isEdit) {
|
||||
Anilist.mutation.postMessage(userId, text, editId)
|
||||
} else {
|
||||
Anilist.mutation.postMessage(userId , text)
|
||||
Anilist.mutation.postMessage(userId, text, isPrivate = private)
|
||||
}
|
||||
|
||||
else -> "Error: Unknown type"
|
||||
}
|
||||
toast(success)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
setNeutralButton(R.string.open_rules) { _, _ ->
|
||||
setNeutralButton(R.string.open_rules) {
|
||||
openLinkInBrowser("https://anilist.co/forum/thread/14")
|
||||
}
|
||||
setNegativeButton(R.string.cancel, null)
|
||||
}.show()
|
||||
setNegButton(R.string.cancel)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.createButton.setOnLongClickListener {
|
||||
binding.previewCheckbox.setOnClickListener {
|
||||
isPreviewMode = !isPreviewMode
|
||||
previewMarkdown(isPreviewMode)
|
||||
if (isPreviewMode) {
|
||||
|
@ -161,7 +166,6 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
} else {
|
||||
toast("Preview disabled")
|
||||
}
|
||||
true
|
||||
}
|
||||
binding.editText.requestFocus()
|
||||
setupMarkdownButtons()
|
||||
|
@ -187,9 +191,11 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
MarkdownFormat.UNORDERED_LIST -> {
|
||||
lines.joinToString("\n") { "- $it" }
|
||||
}
|
||||
|
||||
MarkdownFormat.ORDERED_LIST -> {
|
||||
lines.mapIndexed { index, line -> "${index + 1}. $line" }.joinToString("\n")
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (format.syntax.contains("%s")) {
|
||||
String.format(format.syntax, selectedText)
|
||||
|
@ -222,7 +228,6 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
boxBackgroundMode = TextInputLayout.BOX_BACKGROUND_OUTLINE
|
||||
hint = "Paste your link here"
|
||||
isHintEnabled = true
|
||||
}
|
||||
|
||||
|
@ -241,30 +246,20 @@ class MarkdownCreatorActivity : AppCompatActivity() {
|
|||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
setPadding(64, 64, 64, 0)
|
||||
setPadding(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup).apply {
|
||||
setView(container)
|
||||
setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
customAlertDialog().apply {
|
||||
setTitle("Paste your link here")
|
||||
setCustomView(container)
|
||||
setPosButton(getString(R.string.ok)) {
|
||||
val input = inputEditText.text.toString()
|
||||
val formattedText = String.format(format.syntax, input)
|
||||
binding.editText.text?.insert(position, formattedText)
|
||||
binding.editText.setSelection(position + formattedText.length)
|
||||
dialog.dismiss()
|
||||
}
|
||||
setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
}.create()
|
||||
setNegButton(getString(R.string.cancel))
|
||||
}.show()
|
||||
|
||||
val widthInDp = 245
|
||||
val layoutParams = ViewGroup.LayoutParams(
|
||||
(widthInDp * resources.displayMetrics.density).toInt(),
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
dialog.window?.setLayout(layoutParams.width, layoutParams.height)
|
||||
dialog.show()
|
||||
inputEditText.requestFocus()
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package ani.dantotsu.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
|
@ -20,7 +21,24 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
private var selectedItemIndex: Int = -1
|
||||
private var onItemSelected: ((Int) -> Unit)? = null
|
||||
private var customView: View? = null
|
||||
private var onShow: (() -> Unit)? = null
|
||||
private var attach: ((dialog: AlertDialog) -> Unit)? = null
|
||||
private var onDismiss: (() -> Unit)? = null
|
||||
private var onCancel: (() -> Unit)? = null
|
||||
private var cancelable: Boolean = true
|
||||
fun setCancelable(cancelable: Boolean): AlertDialogBuilder {
|
||||
this.cancelable = cancelable
|
||||
return this
|
||||
}
|
||||
fun setOnShowListener(onShow: () -> Unit): AlertDialogBuilder {
|
||||
this.onShow = onShow
|
||||
return this
|
||||
}
|
||||
fun setOnCancelListener(onCancel: () -> Unit): AlertDialogBuilder {
|
||||
this.onCancel = onCancel
|
||||
return this
|
||||
}
|
||||
|
||||
fun setTitle(title: String?): AlertDialogBuilder {
|
||||
this.title = title
|
||||
return this
|
||||
|
@ -45,6 +63,10 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
this.customView = view
|
||||
return this
|
||||
}
|
||||
fun setCustomView(layoutResId: Int): AlertDialogBuilder {
|
||||
this.customView = View.inflate(context, layoutResId, null)
|
||||
return this
|
||||
}
|
||||
|
||||
fun setPosButton(title: String?, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.posButtonTitle = title
|
||||
|
@ -52,11 +74,7 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun setPosButton(
|
||||
int: Int,
|
||||
formatArgs: Int? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
): AlertDialogBuilder {
|
||||
fun setPosButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.posButtonTitle = context.getString(int, formatArgs)
|
||||
this.onPositiveButtonClick = onClick
|
||||
return this
|
||||
|
@ -68,11 +86,7 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun setNegButton(
|
||||
int: Int,
|
||||
formatArgs: Int? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
): AlertDialogBuilder {
|
||||
fun setNegButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.negButtonTitle = context.getString(int, formatArgs)
|
||||
this.onNegativeButtonClick = onClick
|
||||
return this
|
||||
|
@ -84,11 +98,7 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun setNeutralButton(
|
||||
int: Int,
|
||||
formatArgs: Int? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
): AlertDialogBuilder {
|
||||
fun setNeutralButton(int: Int, formatArgs: Int? = null, onClick: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.neutralButtonTitle = context.getString(int, formatArgs)
|
||||
this.onNeutralButtonClick = onClick
|
||||
return this
|
||||
|
@ -99,22 +109,19 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
return this
|
||||
}
|
||||
|
||||
fun singleChoiceItems(
|
||||
items: Array<String>,
|
||||
selectedItemIndex: Int = -1,
|
||||
onItemSelected: (Int) -> Unit
|
||||
): AlertDialogBuilder {
|
||||
fun onDismiss(onDismiss: (() -> Unit)? = null): AlertDialogBuilder {
|
||||
this.onDismiss = onDismiss
|
||||
return this
|
||||
}
|
||||
|
||||
fun singleChoiceItems(items: Array<String>, selectedItemIndex: Int = -1, onItemSelected: (Int) -> Unit): AlertDialogBuilder {
|
||||
this.items = items
|
||||
this.selectedItemIndex = selectedItemIndex
|
||||
this.onItemSelected = onItemSelected
|
||||
return this
|
||||
}
|
||||
|
||||
fun multiChoiceItems(
|
||||
items: Array<String>,
|
||||
checkedItems: BooleanArray? = null,
|
||||
onItemsSelected: (BooleanArray) -> Unit
|
||||
): AlertDialogBuilder {
|
||||
fun multiChoiceItems(items: Array<String>, checkedItems: BooleanArray? = null, onItemsSelected: (BooleanArray) -> Unit): AlertDialogBuilder {
|
||||
this.items = items
|
||||
this.checkedItems = checkedItems ?: BooleanArray(items.size) { false }
|
||||
this.onItemsSelected = onItemsSelected
|
||||
|
@ -122,15 +129,18 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
}
|
||||
|
||||
fun show() {
|
||||
if (context is Activity && context.isFinishing) return // Ensure context is valid
|
||||
|
||||
val builder = AlertDialog.Builder(context, R.style.MyPopup)
|
||||
if (title != null) builder.setTitle(title)
|
||||
if (message != null) builder.setMessage(message)
|
||||
if (customView != null) builder.setView(customView)
|
||||
if (items != null) {
|
||||
if (onItemSelected != null) {
|
||||
builder.setSingleChoiceItems(items, selectedItemIndex) { _, which ->
|
||||
builder.setSingleChoiceItems(items, selectedItemIndex) { dialog, which ->
|
||||
selectedItemIndex = which
|
||||
onItemSelected?.invoke(which)
|
||||
dialog.dismiss()
|
||||
}
|
||||
} else if (checkedItems != null && onItemsSelected != null) {
|
||||
builder.setMultiChoiceItems(items, checkedItems) { _, which, isChecked ->
|
||||
|
@ -157,15 +167,25 @@ class AlertDialogBuilder(private val context: Context) {
|
|||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
builder.setCancelable(false)
|
||||
if (onCancel != null) {
|
||||
builder.setOnCancelListener {
|
||||
onCancel?.invoke()
|
||||
}
|
||||
}
|
||||
builder.setCancelable(cancelable)
|
||||
val dialog = builder.create()
|
||||
attach?.invoke(dialog)
|
||||
dialog.setOnDismissListener {
|
||||
onDismiss?.invoke()
|
||||
}
|
||||
dialog.setOnShowListener {
|
||||
onShow?.invoke()
|
||||
}
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Context.customAlertDialog(): AlertDialogBuilder {
|
||||
return AlertDialogBuilder(this)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,20 +71,17 @@ class StoragePermissions {
|
|||
complete(true)
|
||||
return
|
||||
}
|
||||
val builder = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
builder.setTitle(getString(R.string.dir_access))
|
||||
builder.setMessage(getString(R.string.dir_access_msg))
|
||||
builder.setPositiveButton(getString(R.string.ok)) { dialog, _ ->
|
||||
launcher.registerForCallback(complete)
|
||||
launcher.launch()
|
||||
dialog.dismiss()
|
||||
}
|
||||
builder.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
complete(false)
|
||||
}
|
||||
val dialog = builder.show()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
customAlertDialog().apply {
|
||||
setTitle(getString(R.string.dir_access))
|
||||
setMessage(getString(R.string.dir_access_msg))
|
||||
setPosButton(getString(R.string.ok)) {
|
||||
launcher.registerForCallback(complete)
|
||||
launcher.launch()
|
||||
}
|
||||
setNegButton(getString(R.string.cancel)) {
|
||||
complete(false)
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
||||
private fun pathToUri(path: String): Uri {
|
||||
|
|
|
@ -64,10 +64,6 @@ internal class ExtensionGithubApi {
|
|||
|
||||
val repos =
|
||||
PrefManager.getVal<Set<String>>(PrefName.AnimeExtensionRepos).toMutableList()
|
||||
if (repos.isEmpty()) {
|
||||
repos.add("https://raw.githubusercontent.com/aniyomiorg/aniyomi-extensions/repo")
|
||||
PrefManager.setVal(PrefName.AnimeExtensionRepos, repos.toSet())
|
||||
}
|
||||
|
||||
repos.forEach {
|
||||
try {
|
||||
|
@ -95,9 +91,10 @@ internal class ExtensionGithubApi {
|
|||
|
||||
// Sanity check - a small number of extensions probably means something broke
|
||||
// with the repo generator
|
||||
if (repoExtensions.size < 10) {
|
||||
throw Exception()
|
||||
}
|
||||
//if (repoExtensions.size < 10) {
|
||||
// throw Exception()
|
||||
//}
|
||||
// No official repo now so this won't be needed anymore. User-made repo can have less than 10 extensions
|
||||
|
||||
extensions.addAll(repoExtensions)
|
||||
} catch (e: Throwable) {
|
||||
|
@ -157,10 +154,6 @@ internal class ExtensionGithubApi {
|
|||
|
||||
val repos =
|
||||
PrefManager.getVal<Set<String>>(PrefName.MangaExtensionRepos).toMutableList()
|
||||
if (repos.isEmpty()) {
|
||||
repos.add("https://raw.githubusercontent.com/keiyoushi/extensions/main")
|
||||
PrefManager.setVal(PrefName.MangaExtensionRepos, repos.toSet())
|
||||
}
|
||||
|
||||
repos.forEach {
|
||||
try {
|
||||
|
@ -188,9 +181,10 @@ internal class ExtensionGithubApi {
|
|||
|
||||
// Sanity check - a small number of extensions probably means something broke
|
||||
// with the repo generator
|
||||
if (repoExtensions.size < 10) {
|
||||
throw Exception()
|
||||
}
|
||||
//if (repoExtensions.size < 10) {
|
||||
// throw Exception()
|
||||
//}
|
||||
// No official repo now so this won't be needed anymore. User made repo can have less than 10 extensions.
|
||||
|
||||
extensions.addAll(repoExtensions)
|
||||
} catch (e: Throwable) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue