reformat
This commit is contained in:
parent
1df528c0dc
commit
afa960c808
171 changed files with 3458 additions and 1915 deletions
|
@ -12,11 +12,17 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.EmptyAdapter
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.databinding.ActivityAuthorBinding
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -31,7 +37,7 @@ class AuthorActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
LangSet.setLocale(this)
|
||||
ThemeManager(this).applyTheme()
|
||||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityAuthorBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ import ani.dantotsu.Refresh
|
|||
import ani.dantotsu.databinding.ActivityListBinding
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.media.user.ListViewPagerAdapter
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -35,7 +35,7 @@ class CalendarActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
LangSet.setLocale(this)
|
||||
ThemeManager(this).applyTheme()
|
||||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityListBinding.inflate(layoutInflater)
|
||||
|
||||
|
||||
|
@ -43,7 +43,11 @@ ThemeManager(this).applyTheme()
|
|||
theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValue, true)
|
||||
val primaryColor = typedValue.data
|
||||
val typedValue2 = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorOnBackground, typedValue2, true)
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorOnBackground,
|
||||
typedValue2,
|
||||
true
|
||||
)
|
||||
val titleTextColor = typedValue2.data
|
||||
val typedValue3 = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue3, true)
|
||||
|
@ -65,10 +69,13 @@ ThemeManager(this).applyTheme()
|
|||
ContextCompat.getColor(this, R.color.nav_bg_inv)
|
||||
binding.root.fitsSystemWindows = true
|
||||
|
||||
}else{
|
||||
} else {
|
||||
binding.root.fitsSystemWindows = false
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||
window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
}
|
||||
setContentView(binding.root)
|
||||
|
||||
|
@ -79,14 +86,15 @@ ThemeManager(this).applyTheme()
|
|||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
this@CalendarActivity.selectedTabIdx = tab?.position ?: 1
|
||||
}
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) { }
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) { }
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {}
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {}
|
||||
})
|
||||
|
||||
model.getCalendar().observe(this) {
|
||||
if (it != null) {
|
||||
binding.listProgressBar.visibility = View.GONE
|
||||
binding.listViewPager.adapter = ListViewPagerAdapter(it.size, true,this)
|
||||
binding.listViewPager.adapter = ListViewPagerAdapter(it.size, true, this)
|
||||
val keys = it.keys.toList()
|
||||
val values = it.values.toList()
|
||||
val savedTab = this.selectedTabIdx
|
||||
|
|
|
@ -21,11 +21,13 @@ class CharacterAdapter(
|
|||
private val characterList: ArrayList<Character>
|
||||
) : RecyclerView.Adapter<CharacterAdapter.CharacterViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CharacterViewHolder {
|
||||
val binding = ItemCharacterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemCharacterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return CharacterViewHolder(binding)
|
||||
}
|
||||
|
||||
private val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
||||
private val uiSettings =
|
||||
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: CharacterViewHolder, position: Int) {
|
||||
|
@ -38,16 +40,23 @@ class CharacterAdapter(
|
|||
}
|
||||
|
||||
override fun getItemCount(): Int = characterList.size
|
||||
inner class CharacterViewHolder(val binding: ItemCharacterBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class CharacterViewHolder(val binding: ItemCharacterBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
val char = characterList[bindingAdapterPosition]
|
||||
ContextCompat.startActivity(
|
||||
itemView.context,
|
||||
Intent(itemView.context, CharacterDetailsActivity::class.java).putExtra("character", char as Serializable),
|
||||
Intent(
|
||||
itemView.context,
|
||||
CharacterDetailsActivity::class.java
|
||||
).putExtra("character", char as Serializable),
|
||||
ActivityOptionsCompat.makeSceneTransitionAnimation(
|
||||
itemView.context as Activity,
|
||||
Pair.create(binding.itemCompactImage, ViewCompat.getTransitionName(binding.itemCompactImage)!!),
|
||||
Pair.create(
|
||||
binding.itemCompactImage,
|
||||
ViewCompat.getTransitionName(binding.itemCompactImage)!!
|
||||
),
|
||||
).toBundle()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -13,13 +13,20 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.databinding.ActivityCharacterBinding
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.ImageViewDialog
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -36,15 +43,17 @@ class CharacterDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChang
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
LangSet.setLocale(this)
|
||||
ThemeManager(this).applyTheme()
|
||||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityCharacterBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
initActivity(this)
|
||||
screenWidth = resources.displayMetrics.run { widthPixels / density }
|
||||
if (uiSettings.immersiveMode) this.window.statusBarColor = ContextCompat.getColor(this, R.color.status)
|
||||
if (uiSettings.immersiveMode) this.window.statusBarColor =
|
||||
ContextCompat.getColor(this, R.color.status)
|
||||
|
||||
val banner = if (uiSettings.bannerAnimations) binding.characterBanner else binding.characterBannerNoKen
|
||||
val banner =
|
||||
if (uiSettings.bannerAnimations) binding.characterBanner else binding.characterBannerNoKen
|
||||
|
||||
banner.updateLayoutParams { height += statusBarHeight }
|
||||
binding.characterClose.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }
|
||||
|
@ -61,7 +70,13 @@ ThemeManager(this).applyTheme()
|
|||
binding.characterTitle.text = character.name
|
||||
banner.loadImage(character.banner)
|
||||
binding.characterCoverImage.loadImage(character.image)
|
||||
binding.characterCoverImage.setOnLongClickListener { ImageViewDialog.newInstance(this, character.name, character.image) }
|
||||
binding.characterCoverImage.setOnLongClickListener {
|
||||
ImageViewDialog.newInstance(
|
||||
this,
|
||||
character.name,
|
||||
character.image
|
||||
)
|
||||
}
|
||||
|
||||
model.getCharacter().observe(this) {
|
||||
if (it != null && !loaded) {
|
||||
|
@ -73,14 +88,15 @@ ThemeManager(this).applyTheme()
|
|||
val roles = character.roles
|
||||
if (roles != null) {
|
||||
val mediaAdaptor = MediaAdaptor(0, roles, this, matchParent = true)
|
||||
val concatAdaptor = ConcatAdapter(CharacterDetailsAdapter(character, this), mediaAdaptor)
|
||||
val concatAdaptor =
|
||||
ConcatAdapter(CharacterDetailsAdapter(character, this), mediaAdaptor)
|
||||
|
||||
val gridSize = (screenWidth / 124f).toInt()
|
||||
val gridLayoutManager = GridLayoutManager(this, gridSize)
|
||||
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return when (position) {
|
||||
0 -> gridSize
|
||||
0 -> gridSize
|
||||
else -> 1
|
||||
}
|
||||
}
|
||||
|
@ -118,16 +134,19 @@ ThemeManager(this).applyTheme()
|
|||
binding.characterCover.scaleY = 1f * cap
|
||||
binding.characterCover.cardElevation = 32f * cap
|
||||
|
||||
binding.characterCover.visibility = if (binding.characterCover.scaleX == 0f) View.GONE else View.VISIBLE
|
||||
binding.characterCover.visibility =
|
||||
if (binding.characterCover.scaleX == 0f) View.GONE else View.VISIBLE
|
||||
|
||||
if (percentage >= percent && !isCollapsed) {
|
||||
isCollapsed = true
|
||||
if (uiSettings.immersiveMode) this.window.statusBarColor = ContextCompat.getColor(this, R.color.nav_bg)
|
||||
if (uiSettings.immersiveMode) this.window.statusBarColor =
|
||||
ContextCompat.getColor(this, R.color.nav_bg)
|
||||
binding.characterAppBar.setBackgroundResource(R.color.nav_bg)
|
||||
}
|
||||
if (percentage <= percent && isCollapsed) {
|
||||
isCollapsed = false
|
||||
if (uiSettings.immersiveMode) this.window.statusBarColor = ContextCompat.getColor(this, R.color.status)
|
||||
if (uiSettings.immersiveMode) this.window.statusBarColor =
|
||||
ContextCompat.getColor(this, R.color.status)
|
||||
binding.characterAppBar.setBackgroundResource(R.color.bg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ import io.noties.markwon.SoftBreakAddsNewLinePlugin
|
|||
class CharacterDetailsAdapter(private val character: Character, private val activity: Activity) :
|
||||
RecyclerView.Adapter<CharacterDetailsAdapter.GenreViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GenreViewHolder {
|
||||
val binding = ItemCharacterDetailsBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemCharacterDetailsBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return GenreViewHolder(binding)
|
||||
}
|
||||
|
||||
|
@ -23,20 +24,22 @@ class CharacterDetailsAdapter(private val character: Character, private val acti
|
|||
override fun onBindViewHolder(holder: GenreViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
val desc =
|
||||
(if (character.age != "null") currActivity()!!.getString(R.string.age) + " " + character.age else "") +
|
||||
(if (character.age != "null") currActivity()!!.getString(R.string.age) + " " + character.age else "") +
|
||||
(if (character.dateOfBirth.toString() != "") currActivity()!!.getString(R.string.birthday) + " " + character.dateOfBirth.toString() else "") +
|
||||
(if (character.gender != "null") currActivity()!!.getString(R.string.gender) + " " + when(character.gender){
|
||||
(if (character.gender != "null") currActivity()!!.getString(R.string.gender) + " " + when (character.gender) {
|
||||
"Male" -> currActivity()!!.getString(R.string.male)
|
||||
"Female" -> currActivity()!!.getString(R.string.female)
|
||||
else -> character.gender
|
||||
} else "") + "\n" + character.description
|
||||
|
||||
binding.characterDesc.isTextSelectable
|
||||
val markWon = Markwon.builder(activity).usePlugin(SoftBreakAddsNewLinePlugin.create()).usePlugin(SpoilerPlugin()).build()
|
||||
val markWon = Markwon.builder(activity).usePlugin(SoftBreakAddsNewLinePlugin.create())
|
||||
.usePlugin(SpoilerPlugin()).build()
|
||||
markWon.setMarkdown(binding.characterDesc, desc)
|
||||
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
inner class GenreViewHolder(val binding: ItemCharacterDetailsBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
inner class GenreViewHolder(val binding: ItemCharacterDetailsBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
|
@ -14,9 +14,9 @@ import ani.dantotsu.databinding.ActivityGenreBinding
|
|||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -28,7 +28,7 @@ class GenreActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
LangSet.setLocale(this)
|
||||
ThemeManager(this).applyTheme()
|
||||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityGenreBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
initActivity(this)
|
||||
|
@ -50,7 +50,8 @@ ThemeManager(this).applyTheme()
|
|||
model.doneListener?.invoke()
|
||||
}
|
||||
binding.mediaInfoGenresRecyclerView.adapter = adapter
|
||||
binding.mediaInfoGenresRecyclerView.layoutManager = GridLayoutManager(this, (screenWidth / 156f).toInt())
|
||||
binding.mediaInfoGenresRecyclerView.layoutManager =
|
||||
GridLayoutManager(this, (screenWidth / 156f).toInt())
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
model.loadGenres(Anilist.genres ?: loadData("genres_list") ?: arrayListOf()) {
|
||||
|
|
|
@ -37,7 +37,8 @@ class GenreAdapter(
|
|||
}
|
||||
|
||||
override fun getItemCount(): Int = genres.size
|
||||
inner class GenreViewHolder(val binding: ItemGenreBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class GenreViewHolder(val binding: ItemGenreBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
ContextCompat.startActivity(
|
||||
|
@ -48,15 +49,15 @@ class GenreAdapter(
|
|||
.putExtra("sortBy", Anilist.sortBy[2])
|
||||
.putExtra("search", true)
|
||||
.also {
|
||||
if (pos[bindingAdapterPosition].lowercase() == "hentai") {
|
||||
if (!Anilist.adult) Toast.makeText(
|
||||
itemView.context,
|
||||
currActivity()?.getString(R.string.content_18),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
it.putExtra("hentai", true)
|
||||
}
|
||||
},
|
||||
if (pos[bindingAdapterPosition].lowercase() == "hentai") {
|
||||
if (!Anilist.adult) Toast.makeText(
|
||||
itemView.context,
|
||||
currActivity()?.getString(R.string.content_18),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
it.putExtra("hentai", true)
|
||||
}
|
||||
},
|
||||
null
|
||||
)
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ data class Media(
|
|||
var userUpdatedAt: Long? = null,
|
||||
var userStartedAt: FuzzyDate = FuzzyDate(),
|
||||
var userCompletedAt: FuzzyDate = FuzzyDate(),
|
||||
var inCustomListsOf: MutableMap<String, Boolean>?= null,
|
||||
var inCustomListsOf: MutableMap<String, Boolean>? = null,
|
||||
var userFavOrder: Int? = null,
|
||||
|
||||
val status: String? = null,
|
||||
|
@ -70,7 +70,7 @@ data class Media(
|
|||
var shareLink: String? = null,
|
||||
var selected: Selected? = null,
|
||||
|
||||
var idKitsu: String?=null,
|
||||
var idKitsu: String? = null,
|
||||
|
||||
var cameFromContinue: Boolean = false
|
||||
) : Serializable {
|
||||
|
|
|
@ -41,20 +41,43 @@ class MediaAdaptor(
|
|||
private val viewPager: ViewPager2? = null,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
||||
private val uiSettings =
|
||||
loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (type) {
|
||||
0 -> MediaViewHolder(ItemMediaCompactBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
1 -> MediaLargeViewHolder(ItemMediaLargeBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
2 -> MediaPageViewHolder(ItemMediaPageBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
3 -> MediaPageSmallViewHolder(
|
||||
0 -> MediaViewHolder(
|
||||
ItemMediaCompactBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
1 -> MediaLargeViewHolder(
|
||||
ItemMediaLargeBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
2 -> MediaPageViewHolder(
|
||||
ItemMediaPageBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
3 -> MediaPageSmallViewHolder(
|
||||
ItemMediaPageSmallBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
|
@ -69,10 +92,12 @@ class MediaAdaptor(
|
|||
val media = mediaList?.getOrNull(position)
|
||||
if (media != null) {
|
||||
b.itemCompactImage.loadImage(media.cover)
|
||||
b.itemCompactOngoing.visibility = if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactOngoing.visibility =
|
||||
if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactTitle.text = media.userPreferredName
|
||||
b.itemCompactScore.text =
|
||||
((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString()
|
||||
((if (media.userScore == 0) (media.meanScore
|
||||
?: 0) else media.userScore) / 10.0).toString()
|
||||
b.itemCompactScoreBG.background = ContextCompat.getDrawable(
|
||||
b.root.context,
|
||||
(if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score)
|
||||
|
@ -104,6 +129,7 @@ class MediaAdaptor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
1 -> {
|
||||
val b = (holder as MediaLargeViewHolder).binding
|
||||
setAnimation(activity, b.root, uiSettings)
|
||||
|
@ -111,22 +137,29 @@ class MediaAdaptor(
|
|||
if (media != null) {
|
||||
b.itemCompactImage.loadImage(media.cover)
|
||||
b.itemCompactBanner.loadImage(media.banner ?: media.cover, 400)
|
||||
b.itemCompactOngoing.visibility = if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactOngoing.visibility =
|
||||
if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactTitle.text = media.userPreferredName
|
||||
b.itemCompactScore.text =
|
||||
((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString()
|
||||
((if (media.userScore == 0) (media.meanScore
|
||||
?: 0) else media.userScore) / 10.0).toString()
|
||||
b.itemCompactScoreBG.background = ContextCompat.getDrawable(
|
||||
b.root.context,
|
||||
(if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score)
|
||||
)
|
||||
if (media.anime != null) {
|
||||
b.itemTotal.text = " " + if ((media.anime.totalEpisodes ?: 0) != 1) currActivity()!!.getString(R.string.episode_plural)
|
||||
else currActivity()!!.getString(R.string.episode_singular)
|
||||
b.itemTotal.text = " " + if ((media.anime.totalEpisodes
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.episode_plural)
|
||||
else currActivity()!!.getString(R.string.episode_singular)
|
||||
b.itemCompactTotal.text =
|
||||
if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " / " + (media.anime.totalEpisodes
|
||||
?: "??").toString()) else (media.anime.totalEpisodes ?: "??").toString()
|
||||
?: "??").toString()) else (media.anime.totalEpisodes
|
||||
?: "??").toString()
|
||||
} else if (media.manga != null) {
|
||||
b.itemTotal.text = " " + if ((media.manga.totalChapters ?: 0) != 1) currActivity()!!.getString(R.string.chapter_plural)
|
||||
b.itemTotal.text = " " + if ((media.manga.totalChapters
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.chapter_plural)
|
||||
else currActivity()!!.getString(R.string.chapter_singular)
|
||||
b.itemCompactTotal.text = "${media.manga.totalChapters ?: "??"}"
|
||||
}
|
||||
|
@ -137,6 +170,7 @@ class MediaAdaptor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
2 -> {
|
||||
val b = (holder as MediaPageViewHolder).binding
|
||||
val media = mediaList?.get(position)
|
||||
|
@ -149,7 +183,8 @@ class MediaAdaptor(
|
|||
AccelerateDecelerateInterpolator()
|
||||
)
|
||||
)
|
||||
val banner = if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
|
||||
val banner =
|
||||
if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
|
||||
val context = b.itemCompactBanner.context
|
||||
if (!(context as Activity).isDestroyed)
|
||||
Glide.with(context as Context)
|
||||
|
@ -157,22 +192,29 @@ class MediaAdaptor(
|
|||
.diskCacheStrategy(DiskCacheStrategy.ALL).override(400)
|
||||
.apply(RequestOptions.bitmapTransform(BlurTransformation(2, 3)))
|
||||
.into(banner)
|
||||
b.itemCompactOngoing.visibility = if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactOngoing.visibility =
|
||||
if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactTitle.text = media.userPreferredName
|
||||
b.itemCompactScore.text =
|
||||
((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString()
|
||||
((if (media.userScore == 0) (media.meanScore
|
||||
?: 0) else media.userScore) / 10.0).toString()
|
||||
b.itemCompactScoreBG.background = ContextCompat.getDrawable(
|
||||
b.root.context,
|
||||
(if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score)
|
||||
)
|
||||
if (media.anime != null) {
|
||||
b.itemTotal.text = " " + if ((media.anime.totalEpisodes ?: 0) != 1) currActivity()!!.getString(R.string.episode_plural)
|
||||
b.itemTotal.text = " " + if ((media.anime.totalEpisodes
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.episode_plural)
|
||||
else currActivity()!!.getString(R.string.episode_singular)
|
||||
b.itemCompactTotal.text =
|
||||
if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " / " + (media.anime.totalEpisodes
|
||||
?: "??").toString()) else (media.anime.totalEpisodes ?: "??").toString()
|
||||
?: "??").toString()) else (media.anime.totalEpisodes
|
||||
?: "??").toString()
|
||||
} else if (media.manga != null) {
|
||||
b.itemTotal.text =" " + if ((media.manga.totalChapters ?: 0) != 1) currActivity()!!.getString(R.string.chapter_plural)
|
||||
b.itemTotal.text = " " + if ((media.manga.totalChapters
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.chapter_plural)
|
||||
else currActivity()!!.getString(R.string.chapter_singular)
|
||||
b.itemCompactTotal.text = "${media.manga.totalChapters ?: "??"}"
|
||||
}
|
||||
|
@ -184,6 +226,7 @@ class MediaAdaptor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
3 -> {
|
||||
val b = (holder as MediaPageSmallViewHolder).binding
|
||||
val media = mediaList?.get(position)
|
||||
|
@ -196,7 +239,8 @@ class MediaAdaptor(
|
|||
AccelerateDecelerateInterpolator()
|
||||
)
|
||||
)
|
||||
val banner = if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
|
||||
val banner =
|
||||
if (uiSettings.bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen
|
||||
val context = b.itemCompactBanner.context
|
||||
if (!(context as Activity).isDestroyed)
|
||||
Glide.with(context as Context)
|
||||
|
@ -204,10 +248,12 @@ class MediaAdaptor(
|
|||
.diskCacheStrategy(DiskCacheStrategy.ALL).override(400)
|
||||
.apply(RequestOptions.bitmapTransform(BlurTransformation(2, 3)))
|
||||
.into(banner)
|
||||
b.itemCompactOngoing.visibility = if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactOngoing.visibility =
|
||||
if (media.status == currActivity()!!.getString(R.string.status_releasing)) View.VISIBLE else View.GONE
|
||||
b.itemCompactTitle.text = media.userPreferredName
|
||||
b.itemCompactScore.text =
|
||||
((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString()
|
||||
((if (media.userScore == 0) (media.meanScore
|
||||
?: 0) else media.userScore) / 10.0).toString()
|
||||
b.itemCompactScoreBG.background = ContextCompat.getDrawable(
|
||||
b.root.context,
|
||||
(if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score)
|
||||
|
@ -222,13 +268,18 @@ class MediaAdaptor(
|
|||
}
|
||||
b.itemCompactStatus.text = media.status ?: ""
|
||||
if (media.anime != null) {
|
||||
b.itemTotal.text = " " + if ((media.anime.totalEpisodes ?: 0) != 1) currActivity()!!.getString(R.string.episode_plural)
|
||||
b.itemTotal.text = " " + if ((media.anime.totalEpisodes
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.episode_plural)
|
||||
else currActivity()!!.getString(R.string.episode_singular)
|
||||
b.itemCompactTotal.text =
|
||||
if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " / " + (media.anime.totalEpisodes
|
||||
?: "??").toString()) else (media.anime.totalEpisodes ?: "??").toString()
|
||||
?: "??").toString()) else (media.anime.totalEpisodes
|
||||
?: "??").toString()
|
||||
} else if (media.manga != null) {
|
||||
b.itemTotal.text = " " + if ((media.manga.totalChapters ?: 0) != 1) currActivity()!!.getString(R.string.chapter_plural)
|
||||
b.itemTotal.text = " " + if ((media.manga.totalChapters
|
||||
?: 0) != 1
|
||||
) currActivity()!!.getString(R.string.chapter_plural)
|
||||
else currActivity()!!.getString(R.string.chapter_singular)
|
||||
b.itemCompactTotal.text = "${media.manga.totalChapters ?: "??"}"
|
||||
}
|
||||
|
@ -249,35 +300,64 @@ class MediaAdaptor(
|
|||
return type
|
||||
}
|
||||
|
||||
inner class MediaViewHolder(val binding: ItemMediaCompactBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class MediaViewHolder(val binding: ItemMediaCompactBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
if (matchParent) itemView.updateLayoutParams { width = -1 }
|
||||
itemView.setSafeOnClickListener { clicked(bindingAdapterPosition, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)) }
|
||||
itemView.setSafeOnClickListener {
|
||||
clicked(
|
||||
bindingAdapterPosition,
|
||||
resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)
|
||||
)
|
||||
}
|
||||
itemView.setOnLongClickListener { longClicked(bindingAdapterPosition) }
|
||||
}
|
||||
}
|
||||
|
||||
inner class MediaLargeViewHolder(val binding: ItemMediaLargeBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class MediaLargeViewHolder(val binding: ItemMediaLargeBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setSafeOnClickListener { clicked(bindingAdapterPosition, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)) }
|
||||
itemView.setSafeOnClickListener {
|
||||
clicked(
|
||||
bindingAdapterPosition,
|
||||
resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)
|
||||
)
|
||||
}
|
||||
itemView.setOnLongClickListener { longClicked(bindingAdapterPosition) }
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
inner class MediaPageViewHolder(val binding: ItemMediaPageBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class MediaPageViewHolder(val binding: ItemMediaPageBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
binding.itemCompactImage.setSafeOnClickListener { clicked(bindingAdapterPosition, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)) }
|
||||
binding.itemCompactImage.setSafeOnClickListener {
|
||||
clicked(
|
||||
bindingAdapterPosition,
|
||||
resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)
|
||||
)
|
||||
}
|
||||
itemView.setOnTouchListener { _, _ -> true }
|
||||
binding.itemCompactImage.setOnLongClickListener { longClicked(bindingAdapterPosition) }
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
inner class MediaPageSmallViewHolder(val binding: ItemMediaPageSmallBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class MediaPageSmallViewHolder(val binding: ItemMediaPageSmallBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
binding.itemCompactImage.setSafeOnClickListener { clicked(bindingAdapterPosition, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)) }
|
||||
binding.itemCompactTitleContainer.setSafeOnClickListener { clicked(bindingAdapterPosition, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)) }
|
||||
binding.itemCompactImage.setSafeOnClickListener {
|
||||
clicked(
|
||||
bindingAdapterPosition,
|
||||
resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)
|
||||
)
|
||||
}
|
||||
binding.itemCompactTitleContainer.setSafeOnClickListener {
|
||||
clicked(
|
||||
bindingAdapterPosition,
|
||||
resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100)
|
||||
)
|
||||
}
|
||||
itemView.setOnTouchListener { _, _ -> true }
|
||||
binding.itemCompactImage.setOnLongClickListener { longClicked(bindingAdapterPosition) }
|
||||
}
|
||||
|
@ -301,7 +381,8 @@ class MediaAdaptor(
|
|||
if ((mediaList?.size ?: 0) > position && position != -1) {
|
||||
val media = mediaList?.get(position) ?: return false
|
||||
if (activity.supportFragmentManager.findFragmentByTag("list") == null) {
|
||||
MediaListDialogSmallFragment.newInstance(media).show(activity.supportFragmentManager, "list")
|
||||
MediaListDialogSmallFragment.newInstance(media)
|
||||
.show(activity.supportFragmentManager, "list")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -317,9 +398,11 @@ class MediaAdaptor(
|
|||
}
|
||||
|
||||
// Create a bitmap with the same dimensions as the drawable
|
||||
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth,
|
||||
val bitmap = Bitmap.createBitmap(
|
||||
drawable.intrinsicWidth,
|
||||
drawable.intrinsicHeight,
|
||||
Bitmap.Config.ARGB_8888)
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
|
||||
// Draw the drawable onto the bitmap
|
||||
val canvas = Canvas(bitmap)
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.annotation.SuppressLint
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.GestureDetector
|
||||
import android.view.MotionEvent
|
||||
|
@ -32,24 +31,24 @@ import ani.dantotsu.R
|
|||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.ZoomOutPageTransformer
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.media.anime.AnimeWatchFragment
|
||||
import ani.dantotsu.copyToClipboard
|
||||
import ani.dantotsu.databinding.ActivityMediaBinding
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.media.anime.AnimeWatchFragment
|
||||
import ani.dantotsu.media.manga.MangaReadFragment
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.media.novel.NovelReadFragment
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.others.ImageViewDialog
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.saveData
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import com.flaviofaria.kenburnsview.RandomTransitionGenerator
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.navigation.NavigationBarView
|
||||
|
|
|
@ -1,28 +1,29 @@
|
|||
package ani.dantotsu.media
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import ani.dantotsu.FileUrl
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.media.anime.Episode
|
||||
import ani.dantotsu.media.anime.SelectorDialogFragment
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.logger
|
||||
import ani.dantotsu.media.anime.Episode
|
||||
import ani.dantotsu.media.anime.SelectorDialogFragment
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.others.AniSkip
|
||||
import ani.dantotsu.others.Jikan
|
||||
import ani.dantotsu.others.Kitsu
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.Book
|
||||
import ani.dantotsu.parsers.MangaImage
|
||||
import ani.dantotsu.parsers.MangaReadSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.parsers.NovelSources
|
||||
import ani.dantotsu.parsers.ShowResponse
|
||||
import ani.dantotsu.parsers.VideoExtractor
|
||||
|
@ -30,25 +31,12 @@ import ani.dantotsu.parsers.WatchSources
|
|||
import ani.dantotsu.saveData
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.tryWithSuspend
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.download.Download
|
||||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.AniyomiAdapter
|
||||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.HAnimeSources
|
||||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
|
||||
class MediaDetailsViewModel : ViewModel() {
|
||||
val scrolledToTop = MutableLiveData(true)
|
||||
|
@ -62,8 +50,8 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
val sharedPreferences = Injekt.get<SharedPreferences>()
|
||||
val data = loadData<Selected>("${media.id}-select") ?: Selected().let {
|
||||
it.sourceIndex = if (media.isAdult) 0 else when (media.anime != null) {
|
||||
true ->sharedPreferences.getInt("settings_def_anime_source_s_r", 0)
|
||||
else ->sharedPreferences.getInt(("settings_def_manga_source_s_r"), 0)
|
||||
true -> sharedPreferences.getInt("settings_def_anime_source_s_r", 0)
|
||||
else -> sharedPreferences.getInt(("settings_def_manga_source_s_r"), 0)
|
||||
}
|
||||
it.preferDub = loadData("settings_prefer_dub") ?: false
|
||||
saveSelected(media.id, it)
|
||||
|
@ -81,7 +69,9 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
fun loadSelectedStringLocation(sourceName: String): Int {
|
||||
//find the location of the source in the list
|
||||
var location = watchSources?.list?.indexOfFirst { it.name == sourceName } ?: 0
|
||||
if (location == -1) {location = 0}
|
||||
if (location == -1) {
|
||||
location = 0
|
||||
}
|
||||
return location
|
||||
}
|
||||
|
||||
|
@ -106,7 +96,9 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
|
||||
|
||||
//Anime
|
||||
private val kitsuEpisodes: MutableLiveData<Map<String, Episode>> = MutableLiveData<Map<String, Episode>>(null)
|
||||
private val kitsuEpisodes: MutableLiveData<Map<String, Episode>> =
|
||||
MutableLiveData<Map<String, Episode>>(null)
|
||||
|
||||
fun getKitsuEpisodes(): LiveData<Map<String, Episode>> = kitsuEpisodes
|
||||
suspend fun loadKitsuEpisodes(s: Media) {
|
||||
tryWithSuspend {
|
||||
|
@ -114,7 +106,9 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
private val fillerEpisodes: MutableLiveData<Map<String, Episode>> = MutableLiveData<Map<String, Episode>>(null)
|
||||
private val fillerEpisodes: MutableLiveData<Map<String, Episode>> =
|
||||
MutableLiveData<Map<String, Episode>>(null)
|
||||
|
||||
fun getFillerEpisodes(): LiveData<Map<String, Episode>> = fillerEpisodes
|
||||
suspend fun loadFillerEpisodes(s: Media) {
|
||||
tryWithSuspend {
|
||||
|
@ -145,7 +139,8 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
|
||||
suspend fun overrideEpisodes(i: Int, source: ShowResponse, id: Int) {
|
||||
watchSources?.saveResponse(i, id, source)
|
||||
epsLoaded[i] = watchSources?.loadEpisodes(i, source.link, source.extra, source.sAnime) ?: return
|
||||
epsLoaded[i] =
|
||||
watchSources?.loadEpisodes(i, source.link, source.extra, source.sAnime) ?: return
|
||||
episodes.postValue(epsLoaded)
|
||||
}
|
||||
|
||||
|
@ -184,7 +179,12 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
|
||||
val timeStamps = MutableLiveData<List<AniSkip.Stamp>?>()
|
||||
private val timeStampsMap: MutableMap<Int, List<AniSkip.Stamp>?> = mutableMapOf()
|
||||
suspend fun loadTimeStamps(malId: Int?, episodeNum: Int?, duration: Long, useProxyForTimeStamps: Boolean) {
|
||||
suspend fun loadTimeStamps(
|
||||
malId: Int?,
|
||||
episodeNum: Int?,
|
||||
duration: Long,
|
||||
useProxyForTimeStamps: Boolean
|
||||
) {
|
||||
malId ?: return
|
||||
episodeNum ?: return
|
||||
if (timeStampsMap.containsKey(episodeNum))
|
||||
|
@ -194,7 +194,11 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
timeStamps.postValue(result)
|
||||
}
|
||||
|
||||
suspend fun loadEpisodeSingleVideo(ep: Episode, selected: Selected, post: Boolean = true): Boolean {
|
||||
suspend fun loadEpisodeSingleVideo(
|
||||
ep: Episode,
|
||||
selected: Selected,
|
||||
post: Boolean = true
|
||||
): Boolean {
|
||||
if (ep.extractors.isNullOrEmpty()) {
|
||||
|
||||
val server = selected.server ?: return false
|
||||
|
@ -204,8 +208,10 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
selected.sourceIndex = selected.sourceIndex
|
||||
if (!post && !it.allowsPreloading) null
|
||||
else ep.sEpisode?.let { it1 ->
|
||||
it.loadSingleVideoServer(server, link, ep.extra,
|
||||
it1, post)
|
||||
it.loadSingleVideoServer(
|
||||
server, link, ep.extra,
|
||||
it1, post
|
||||
)
|
||||
}
|
||||
} ?: return false)
|
||||
ep.allStreams = false
|
||||
|
@ -228,7 +234,13 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
val epChanged = MutableLiveData(true)
|
||||
fun onEpisodeClick(media: Media, i: String, manager: FragmentManager, launch: Boolean = true, prevEp: String? = null) {
|
||||
fun onEpisodeClick(
|
||||
media: Media,
|
||||
i: String,
|
||||
manager: FragmentManager,
|
||||
launch: Boolean = true,
|
||||
prevEp: String? = null
|
||||
) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
if (manager.findFragmentByTag("dialog") == null && !manager.isDestroyed) {
|
||||
if (media.anime?.episodes?.get(i) != null) {
|
||||
|
@ -238,7 +250,8 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
return@post
|
||||
}
|
||||
media.selected = this.loadSelected(media)
|
||||
val selector = SelectorDialogFragment.newInstance(media.selected!!.server, launch, prevEp)
|
||||
val selector =
|
||||
SelectorDialogFragment.newInstance(media.selected!!.server, launch, prevEp)
|
||||
selector.show(manager, "dialog")
|
||||
}
|
||||
}
|
||||
|
@ -248,13 +261,17 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
//Manga
|
||||
var mangaReadSources: MangaReadSources? = null
|
||||
|
||||
private val mangaChapters = MutableLiveData<MutableMap<Int, MutableMap<String, MangaChapter>>>(null)
|
||||
private val mangaChapters =
|
||||
MutableLiveData<MutableMap<Int, MutableMap<String, MangaChapter>>>(null)
|
||||
private val mangaLoaded = mutableMapOf<Int, MutableMap<String, MangaChapter>>()
|
||||
fun getMangaChapters(): LiveData<MutableMap<Int, MutableMap<String, MangaChapter>>> = mangaChapters
|
||||
fun getMangaChapters(): LiveData<MutableMap<Int, MutableMap<String, MangaChapter>>> =
|
||||
mangaChapters
|
||||
|
||||
suspend fun loadMangaChapters(media: Media, i: Int, invalidate: Boolean = false) {
|
||||
logger("Loading Manga Chapters : $mangaLoaded")
|
||||
if (!mangaLoaded.containsKey(i) || invalidate) tryWithSuspend {
|
||||
mangaLoaded[i] = mangaReadSources?.loadChaptersFromMedia(i, media) ?: return@tryWithSuspend
|
||||
mangaLoaded[i] =
|
||||
mangaReadSources?.loadChaptersFromMedia(i, media) ?: return@tryWithSuspend
|
||||
}
|
||||
mangaChapters.postValue(mangaLoaded)
|
||||
}
|
||||
|
@ -269,11 +286,17 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
|
||||
private val mangaChapter = MutableLiveData<MangaChapter?>(null)
|
||||
fun getMangaChapter(): LiveData<MangaChapter?> = mangaChapter
|
||||
suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, series: String, post: Boolean = true): Boolean {
|
||||
|
||||
suspend fun loadMangaChapterImages(
|
||||
chapter: MangaChapter,
|
||||
selected: Selected,
|
||||
series: String,
|
||||
post: Boolean = true
|
||||
): Boolean {
|
||||
|
||||
return tryWithSuspend(true) {
|
||||
chapter.addImages(
|
||||
mangaReadSources?.get(selected.sourceIndex)?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false
|
||||
mangaReadSources?.get(selected.sourceIndex)
|
||||
?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false
|
||||
)
|
||||
if (post) mangaChapter.postValue(chapter)
|
||||
true
|
||||
|
@ -281,7 +304,8 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
fun loadTransformation(mangaImage: MangaImage, source: Int): BitmapTransformation? {
|
||||
return if (mangaImage.useTransformation) mangaReadSources?.get(source)?.getTransformation() else null
|
||||
return if (mangaImage.useTransformation) mangaReadSources?.get(source)
|
||||
?.getTransformation() else null
|
||||
}
|
||||
|
||||
val novelSources = NovelSources
|
||||
|
@ -296,7 +320,7 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
suspend fun autoSearchNovels(media: Media) {
|
||||
val source = novelSources[media.selected?.sourceIndex?:0]
|
||||
val source = novelSources[media.selected?.sourceIndex ?: 0]
|
||||
tryWithSuspend(post = true) {
|
||||
if (source != null) {
|
||||
novelResponses.postValue(source.sortedSearch(media))
|
||||
|
@ -307,7 +331,9 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
val book: MutableLiveData<Book> = MutableLiveData(null)
|
||||
suspend fun loadBook(novel: ShowResponse, i: Int) {
|
||||
tryWithSuspend {
|
||||
book.postValue(novelSources[i]?.loadBook(novel.link, novel.extra) ?: return@tryWithSuspend)
|
||||
book.postValue(
|
||||
novelSources[i]?.loadBook(novel.link, novel.extra) ?: return@tryWithSuspend
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,11 @@ class MediaInfoFragment : Fragment() {
|
|||
private var type = "ANIME"
|
||||
private val genreModel: GenresViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentMediaInfoBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -59,8 +63,8 @@ class MediaInfoFragment : Fragment() {
|
|||
binding.mediaInfoContainer.visibility = if (loaded) View.VISIBLE else View.GONE
|
||||
binding.mediaInfoContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin += 128f.px + navBarHeight }
|
||||
|
||||
model.scrolledToTop.observe(viewLifecycleOwner){
|
||||
if(it) binding.mediaInfoScroll.scrollTo(0,0)
|
||||
model.scrolledToTop.observe(viewLifecycleOwner) {
|
||||
if (it) binding.mediaInfoScroll.scrollTo(0, 0)
|
||||
}
|
||||
|
||||
model.getMedia().observe(viewLifecycleOwner) { media ->
|
||||
|
@ -68,30 +72,32 @@ class MediaInfoFragment : Fragment() {
|
|||
loaded = true
|
||||
binding.mediaInfoProgressBar.visibility = View.GONE
|
||||
binding.mediaInfoContainer.visibility = View.VISIBLE
|
||||
binding.mediaInfoName.text = "\t\t\t" + (media.name?:media.nameRomaji)
|
||||
binding.mediaInfoName.text = "\t\t\t" + (media.name ?: media.nameRomaji)
|
||||
binding.mediaInfoName.setOnLongClickListener {
|
||||
copyToClipboard(media.name?:media.nameRomaji)
|
||||
copyToClipboard(media.name ?: media.nameRomaji)
|
||||
true
|
||||
}
|
||||
if (media.name != null) binding.mediaInfoNameRomajiContainer.visibility = View.VISIBLE
|
||||
if (media.name != null) binding.mediaInfoNameRomajiContainer.visibility =
|
||||
View.VISIBLE
|
||||
binding.mediaInfoNameRomaji.text = "\t\t\t" + media.nameRomaji
|
||||
binding.mediaInfoNameRomaji.setOnLongClickListener {
|
||||
copyToClipboard(media.nameRomaji)
|
||||
true
|
||||
}
|
||||
binding.mediaInfoMeanScore.text = if (media.meanScore != null) (media.meanScore / 10.0).toString() else "??"
|
||||
binding.mediaInfoMeanScore.text =
|
||||
if (media.meanScore != null) (media.meanScore / 10.0).toString() else "??"
|
||||
binding.mediaInfoStatus.text = media.status
|
||||
binding.mediaInfoFormat.text = media.format
|
||||
binding.mediaInfoSource.text = media.source
|
||||
binding.mediaInfoStart.text = media.startDate?.toString() ?: "??"
|
||||
binding.mediaInfoEnd.text =media.endDate?.toString() ?: "??"
|
||||
binding.mediaInfoEnd.text = media.endDate?.toString() ?: "??"
|
||||
if (media.anime != null) {
|
||||
binding.mediaInfoDuration.text =
|
||||
if (media.anime.episodeDuration != null) media.anime.episodeDuration.toString() else "??"
|
||||
binding.mediaInfoDurationContainer.visibility = View.VISIBLE
|
||||
binding.mediaInfoSeasonContainer.visibility = View.VISIBLE
|
||||
binding.mediaInfoSeason.text =
|
||||
(media.anime.season ?: "??")+ " " + (media.anime.seasonYear ?: "??")
|
||||
(media.anime.season ?: "??") + " " + (media.anime.seasonYear ?: "??")
|
||||
if (media.anime.mainStudio != null) {
|
||||
binding.mediaInfoStudioContainer.visibility = View.VISIBLE
|
||||
binding.mediaInfoStudio.text = media.anime.mainStudio!!.name
|
||||
|
@ -246,7 +252,12 @@ class MediaInfoFragment : Fragment() {
|
|||
val end = a.indexOf('"', first).let { if (it != -1) it else return a }
|
||||
val name = a.subSequence(first, end).toString()
|
||||
return "${a.subSequence(0, first)}" +
|
||||
"[$name](https://www.youtube.com/results?search_query=${URLEncoder.encode(name, "utf-8")})" +
|
||||
"[$name](https://www.youtube.com/results?search_query=${
|
||||
URLEncoder.encode(
|
||||
name,
|
||||
"utf-8"
|
||||
)
|
||||
})" +
|
||||
"${a.subSequence(end, a.length)}"
|
||||
}
|
||||
|
||||
|
@ -270,7 +281,11 @@ class MediaInfoFragment : Fragment() {
|
|||
}
|
||||
|
||||
if (media.anime.op.isNotEmpty()) {
|
||||
val bind = ItemTitleTextBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||
val bind = ItemTitleTextBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
bind.itemTitle.setText(R.string.opening)
|
||||
makeText(bind.itemText, media.anime.op)
|
||||
parent.addView(bind.root)
|
||||
|
@ -278,7 +293,11 @@ class MediaInfoFragment : Fragment() {
|
|||
|
||||
|
||||
if (media.anime.ed.isNotEmpty()) {
|
||||
val bind = ItemTitleTextBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||
val bind = ItemTitleTextBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
bind.itemTitle.setText(R.string.ending)
|
||||
makeText(bind.itemText, media.anime.ed)
|
||||
parent.addView(bind.root)
|
||||
|
@ -458,7 +477,8 @@ class MediaInfoFragment : Fragment() {
|
|||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val cornerTop = ObjectAnimator.ofFloat(binding.root, "radius", 0f, 32f).setDuration(200)
|
||||
val cornerNotTop = ObjectAnimator.ofFloat(binding.root, "radius", 32f, 0f).setDuration(200)
|
||||
val cornerNotTop =
|
||||
ObjectAnimator.ofFloat(binding.root, "radius", 32f, 0f).setDuration(200)
|
||||
var cornered = true
|
||||
cornerTop.start()
|
||||
binding.mediaInfoScroll.setOnScrollChangeListener { v, _, _, _, _ ->
|
||||
|
|
|
@ -14,8 +14,8 @@ import androidx.lifecycle.lifecycleScope
|
|||
import ani.dantotsu.*
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.api.FuzzyDate
|
||||
import ani.dantotsu.databinding.BottomSheetMediaListBinding
|
||||
import ani.dantotsu.connections.mal.MAL
|
||||
import ani.dantotsu.databinding.BottomSheetMediaListBinding
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -27,7 +27,11 @@ class MediaListDialogFragment : BottomSheetDialogFragment() {
|
|||
private var _binding: BottomSheetMediaListBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetMediaListBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -46,9 +50,13 @@ class MediaListDialogFragment : BottomSheetDialogFragment() {
|
|||
binding.mediaListLayout.visibility = View.VISIBLE
|
||||
|
||||
val statuses: Array<String> = resources.getStringArray(R.array.status)
|
||||
val statusStrings = if (media?.manga==null) resources.getStringArray(R.array.status_anime) else resources.getStringArray(R.array.status_manga)
|
||||
val userStatus = if(media!!.userStatus != null) statusStrings[statuses.indexOf(media!!.userStatus)] else statusStrings[0]
|
||||
|
||||
val statusStrings =
|
||||
if (media?.manga == null) resources.getStringArray(R.array.status_anime) else resources.getStringArray(
|
||||
R.array.status_manga
|
||||
)
|
||||
val userStatus =
|
||||
if (media!!.userStatus != null) statusStrings[statuses.indexOf(media!!.userStatus)] else statusStrings[0]
|
||||
|
||||
binding.mediaListStatus.setText(userStatus)
|
||||
binding.mediaListStatus.setAdapter(
|
||||
ArrayAdapter(
|
||||
|
@ -160,7 +168,9 @@ class MediaListDialogFragment : BottomSheetDialogFragment() {
|
|||
val init =
|
||||
if (binding.mediaListProgress.text.toString() != "") binding.mediaListProgress.text.toString()
|
||||
.toInt() else 0
|
||||
if (init < (total ?: 5000)) binding.mediaListProgress.setText((init + 1).toString())
|
||||
if (init < (total
|
||||
?: 5000)
|
||||
) binding.mediaListProgress.setText((init + 1).toString())
|
||||
if (init + 1 == (total ?: 5000)) {
|
||||
binding.mediaListStatus.setText(statusStrings[2], false)
|
||||
onComplete()
|
||||
|
@ -201,11 +211,15 @@ class MediaListDialogFragment : BottomSheetDialogFragment() {
|
|||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
if (media != null) {
|
||||
val progress = _binding?.mediaListProgress?.text.toString().toIntOrNull()
|
||||
val progress =
|
||||
_binding?.mediaListProgress?.text.toString().toIntOrNull()
|
||||
val score =
|
||||
(_binding?.mediaListScore?.text.toString().toDoubleOrNull()?.times(10))?.toInt()
|
||||
val status = statuses[statusStrings.indexOf(_binding?.mediaListStatus?.text.toString())]
|
||||
val rewatch = _binding?.mediaListRewatch?.text?.toString()?.toIntOrNull()
|
||||
(_binding?.mediaListScore?.text.toString().toDoubleOrNull()
|
||||
?.times(10))?.toInt()
|
||||
val status =
|
||||
statuses[statusStrings.indexOf(_binding?.mediaListStatus?.text.toString())]
|
||||
val rewatch =
|
||||
_binding?.mediaListRewatch?.text?.toString()?.toIntOrNull()
|
||||
val notes = _binding?.mediaListNotes?.text?.toString()
|
||||
val startD = start.date
|
||||
val endD = end.date
|
||||
|
@ -245,7 +259,7 @@ class MediaListDialogFragment : BottomSheetDialogFragment() {
|
|||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
Anilist.mutation.deleteList(id)
|
||||
MAL.query.deleteList(media?.anime!=null,media?.idMAL)
|
||||
MAL.query.deleteList(media?.anime != null, media?.idMAL)
|
||||
}
|
||||
Refresh.all()
|
||||
snackString(getString(R.string.deleted_from_list))
|
||||
|
|
|
@ -12,11 +12,9 @@ import androidx.core.view.updateLayoutParams
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.databinding.BottomSheetMediaListSmallBinding
|
||||
import ani.dantotsu.connections.mal.MAL
|
||||
import ani.dantotsu.databinding.BottomSheetMediaListSmallBinding
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -46,7 +44,11 @@ class MediaListDialogSmallFragment : BottomSheetDialogFragment() {
|
|||
private var _binding: BottomSheetMediaListSmallBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetMediaListSmallBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -60,8 +62,12 @@ class MediaListDialogSmallFragment : BottomSheetDialogFragment() {
|
|||
binding.mediaListProgressBar.visibility = View.GONE
|
||||
binding.mediaListLayout.visibility = View.VISIBLE
|
||||
val statuses: Array<String> = resources.getStringArray(R.array.status)
|
||||
val statusStrings = if (media.manga==null) resources.getStringArray(R.array.status_anime) else resources.getStringArray(R.array.status_manga)
|
||||
val userStatus = if(media.userStatus != null) statusStrings[statuses.indexOf(media.userStatus)] else statusStrings[0]
|
||||
val statusStrings =
|
||||
if (media.manga == null) resources.getStringArray(R.array.status_anime) else resources.getStringArray(
|
||||
R.array.status_manga
|
||||
)
|
||||
val userStatus =
|
||||
if (media.userStatus != null) statusStrings[statuses.indexOf(media.userStatus)] else statusStrings[0]
|
||||
|
||||
binding.mediaListStatus.setText(userStatus)
|
||||
binding.mediaListStatus.setAdapter(
|
||||
|
@ -130,10 +136,26 @@ class MediaListDialogSmallFragment : BottomSheetDialogFragment() {
|
|||
withContext(Dispatchers.IO) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val progress = _binding?.mediaListProgress?.text.toString().toIntOrNull()
|
||||
val score = (_binding?.mediaListScore?.text.toString().toDoubleOrNull()?.times(10))?.toInt()
|
||||
val status = statuses[statusStrings.indexOf(_binding?.mediaListStatus?.text.toString())]
|
||||
Anilist.mutation.editList(media.id, progress, score, null, null, status, media.isListPrivate)
|
||||
MAL.query.editList(media.idMAL, media.anime != null, progress, score, status)
|
||||
val score = (_binding?.mediaListScore?.text.toString().toDoubleOrNull()
|
||||
?.times(10))?.toInt()
|
||||
val status =
|
||||
statuses[statusStrings.indexOf(_binding?.mediaListStatus?.text.toString())]
|
||||
Anilist.mutation.editList(
|
||||
media.id,
|
||||
progress,
|
||||
score,
|
||||
null,
|
||||
null,
|
||||
status,
|
||||
media.isListPrivate
|
||||
)
|
||||
MAL.query.editList(
|
||||
media.idMAL,
|
||||
media.anime != null,
|
||||
progress,
|
||||
score,
|
||||
status
|
||||
)
|
||||
}
|
||||
}
|
||||
Refresh.all()
|
||||
|
|
|
@ -5,7 +5,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
|
||||
class OtherDetailsViewModel : ViewModel() {
|
||||
private val character: MutableLiveData<Character> = MutableLiveData(null)
|
||||
|
@ -19,26 +19,28 @@ class OtherDetailsViewModel : ViewModel() {
|
|||
suspend fun loadStudio(m: Studio) {
|
||||
if (studio.value == null) studio.postValue(Anilist.query.getStudioDetails(m))
|
||||
}
|
||||
|
||||
private val author: MutableLiveData<Author> = MutableLiveData(null)
|
||||
fun getAuthor(): LiveData<Author> = author
|
||||
suspend fun loadAuthor(m: Author) {
|
||||
if (author.value == null) author.postValue(Anilist.query.getAuthorDetails(m))
|
||||
}
|
||||
private val calendar: MutableLiveData<Map<String,MutableList<Media>>> = MutableLiveData(null)
|
||||
fun getCalendar(): LiveData<Map<String,MutableList<Media>>> = calendar
|
||||
|
||||
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(false,curr-86400,curr+(86400*6))
|
||||
val curr = System.currentTimeMillis() / 1000
|
||||
val res = Anilist.query.recentlyUpdated(false, curr - 86400, curr + (86400 * 6))
|
||||
val df = DateFormat.getDateInstance(DateFormat.FULL)
|
||||
val map = mutableMapOf<String,MutableList<Media>>()
|
||||
val idMap = mutableMapOf<String,MutableList<Int>>()
|
||||
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 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)) {
|
||||
if (!idList.contains(it.id)) {
|
||||
idList.add(it.id)
|
||||
list.add(it)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ class ProgressAdapter(private val horizontal: Boolean = true, searched: Boolean)
|
|||
var bar: ProgressBar? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProgressViewHolder {
|
||||
val binding = ItemProgressbarBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemProgressbarBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ProgressViewHolder(binding)
|
||||
}
|
||||
|
||||
|
@ -33,7 +34,12 @@ class ProgressAdapter(private val horizontal: Boolean = true, searched: Boolean)
|
|||
val doubleClickDetector = GestureDetector(progressBar.context, object : GesturesListener() {
|
||||
override fun onDoubleClick(event: MotionEvent) {
|
||||
snackString(currContext()?.getString(R.string.cant_wait))
|
||||
ObjectAnimator.ofFloat(progressBar, "translationX", progressBar.translationX, progressBar.translationX + 100f)
|
||||
ObjectAnimator.ofFloat(
|
||||
progressBar,
|
||||
"translationX",
|
||||
progressBar.translationX,
|
||||
progressBar.translationX + 100f
|
||||
)
|
||||
.setDuration(300).start()
|
||||
}
|
||||
|
||||
|
@ -51,7 +57,8 @@ class ProgressAdapter(private val horizontal: Boolean = true, searched: Boolean)
|
|||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
inner class ProgressViewHolder(val binding: ItemProgressbarBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class ProgressViewHolder(val binding: ItemProgressbarBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.updateLayoutParams { if (horizontal) width = -1 else height = -1 }
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ import ani.dantotsu.connections.anilist.Anilist
|
|||
import ani.dantotsu.connections.anilist.AnilistSearch
|
||||
import ani.dantotsu.connections.anilist.SearchResults
|
||||
import ani.dantotsu.databinding.ActivitySearchBinding
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
|
@ -35,12 +35,12 @@ class SearchActivity : AppCompatActivity() {
|
|||
private lateinit var concatAdapter: ConcatAdapter
|
||||
|
||||
lateinit var result: SearchResults
|
||||
lateinit var updateChips: (()->Unit)
|
||||
lateinit var updateChips: (() -> Unit)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
LangSet.setLocale(this)
|
||||
ThemeManager(this).applyTheme()
|
||||
ThemeManager(this).applyTheme()
|
||||
binding = ActivitySearchBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
initActivity(this)
|
||||
|
@ -83,10 +83,10 @@ ThemeManager(this).applyTheme()
|
|||
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return when (position) {
|
||||
0 -> gridSize
|
||||
0 -> gridSize
|
||||
concatAdapter.itemCount - 1 -> gridSize
|
||||
else -> when (style) {
|
||||
0 -> 1
|
||||
else -> when (style) {
|
||||
0 -> 1
|
||||
else -> gridSize
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ ThemeManager(this).applyTheme()
|
|||
} else
|
||||
headerAdaptor.requestFocus?.run()
|
||||
|
||||
if(intent.getBooleanExtra("search",false)) search()
|
||||
if (intent.getBooleanExtra("search", false)) search()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,14 +20,16 @@ import ani.dantotsu.saveData
|
|||
import com.google.android.material.checkbox.MaterialCheckBox.*
|
||||
|
||||
|
||||
class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter<SearchAdapter.SearchHeaderViewHolder>() {
|
||||
class SearchAdapter(private val activity: SearchActivity) :
|
||||
RecyclerView.Adapter<SearchAdapter.SearchHeaderViewHolder>() {
|
||||
private val itemViewType = 6969
|
||||
var search: Runnable? = null
|
||||
var requestFocus: Runnable? = null
|
||||
private var textWatcher: TextWatcher? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchHeaderViewHolder {
|
||||
val binding = ItemSearchHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemSearchHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return SearchHeaderViewHolder(binding)
|
||||
}
|
||||
|
||||
|
@ -36,13 +38,15 @@ class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter
|
|||
val binding = holder.binding
|
||||
|
||||
|
||||
val imm: InputMethodManager = activity.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
val imm: InputMethodManager =
|
||||
activity.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
|
||||
when (activity.style) {
|
||||
0 -> {
|
||||
binding.searchResultGrid.alpha = 1f
|
||||
binding.searchResultList.alpha = 0.33f
|
||||
}
|
||||
|
||||
1 -> {
|
||||
binding.searchResultList.alpha = 1f
|
||||
binding.searchResultGrid.alpha = 0.33f
|
||||
|
@ -62,7 +66,8 @@ class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter
|
|||
binding.searchChipRecycler.adapter = SearchChipAdapter(activity).also {
|
||||
activity.updateChips = { it.update() }
|
||||
}
|
||||
binding.searchChipRecycler.layoutManager = LinearLayoutManager(binding.root.context, HORIZONTAL, false)
|
||||
binding.searchChipRecycler.layoutManager =
|
||||
LinearLayoutManager(binding.root.context, HORIZONTAL, false)
|
||||
|
||||
binding.searchFilter.setOnClickListener {
|
||||
SearchFilterBottomDialog.newInstance().show(activity.supportFragmentManager, "dialog")
|
||||
|
@ -70,7 +75,8 @@ class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter
|
|||
|
||||
fun searchTitle() {
|
||||
activity.result.apply {
|
||||
search = if (binding.searchBarText.text.toString() != "") binding.searchBarText.text.toString() else null
|
||||
search =
|
||||
if (binding.searchBarText.text.toString() != "") binding.searchBarText.text.toString() else null
|
||||
onList = listOnly
|
||||
isAdult = adult
|
||||
}
|
||||
|
@ -96,7 +102,8 @@ class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter
|
|||
imm.hideSoftInputFromWindow(binding.searchBarText.windowToken, 0)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
binding.searchBar.setEndIconOnClickListener { searchTitle() }
|
||||
|
@ -127,7 +134,7 @@ class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter
|
|||
binding.searchList.apply {
|
||||
if (Anilist.userid != null) {
|
||||
visibility = View.VISIBLE
|
||||
checkedState = when(listOnly){
|
||||
checkedState = when (listOnly) {
|
||||
null -> STATE_UNCHECKED
|
||||
true -> STATE_CHECKED
|
||||
false -> STATE_INDETERMINATE
|
||||
|
@ -135,10 +142,10 @@ class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter
|
|||
|
||||
addOnCheckedStateChangedListener { _, state ->
|
||||
listOnly = when (state) {
|
||||
STATE_CHECKED -> true
|
||||
STATE_CHECKED -> true
|
||||
STATE_INDETERMINATE -> false
|
||||
STATE_UNCHECKED -> null
|
||||
else -> null
|
||||
STATE_UNCHECKED -> null
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,20 +165,24 @@ class SearchAdapter(private val activity: SearchActivity) : RecyclerView.Adapter
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class SearchHeaderViewHolder(val binding: ItemSearchHeaderBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
inner class SearchHeaderViewHolder(val binding: ItemSearchHeaderBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return itemViewType
|
||||
}
|
||||
|
||||
|
||||
class SearchChipAdapter(val activity: SearchActivity) : RecyclerView.Adapter<SearchChipAdapter.SearchChipViewHolder>() {
|
||||
class SearchChipAdapter(val activity: SearchActivity) :
|
||||
RecyclerView.Adapter<SearchChipAdapter.SearchChipViewHolder>() {
|
||||
private var chips = activity.result.toChipList()
|
||||
|
||||
inner class SearchChipViewHolder(val binding: ItemChipBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
inner class SearchChipViewHolder(val binding: ItemChipBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchChipViewHolder {
|
||||
val binding = ItemChipBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemChipBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return SearchChipViewHolder(binding)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,13 +18,17 @@ import ani.dantotsu.databinding.BottomSheetSearchFilterBinding
|
|||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import com.google.android.material.chip.Chip
|
||||
|
||||
class SearchFilterBottomDialog() : BottomSheetDialogFragment() {
|
||||
class SearchFilterBottomDialog : BottomSheetDialogFragment() {
|
||||
private var _binding: BottomSheetSearchFilterBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private lateinit var activity: SearchActivity
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetSearchFilterBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -99,7 +103,7 @@ class SearchFilterBottomDialog() : BottomSheetDialogFragment() {
|
|||
ArrayAdapter(
|
||||
binding.root.context,
|
||||
R.layout.item_dropdown,
|
||||
(1970 until 2025).map { it.toString() }.reversed().toTypedArray()
|
||||
(1970 until 2025).map { it.toString() }.reversed().toTypedArray()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -129,24 +133,25 @@ class SearchFilterBottomDialog() : BottomSheetDialogFragment() {
|
|||
}
|
||||
binding.searchGenresGrid.isChecked = false
|
||||
|
||||
binding.searchFilterTags.adapter = FilterChipAdapter(Anilist.tags?.get(activity.result.isAdult) ?: listOf()) { chip ->
|
||||
val tag = chip.text.toString()
|
||||
chip.isChecked = selectedTags.contains(tag)
|
||||
chip.isCloseIconVisible = exTags.contains(tag)
|
||||
chip.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (isChecked) {
|
||||
chip.isCloseIconVisible = false
|
||||
exTags.remove(tag)
|
||||
selectedTags.add(tag)
|
||||
} else
|
||||
selectedTags.remove(tag)
|
||||
binding.searchFilterTags.adapter =
|
||||
FilterChipAdapter(Anilist.tags?.get(activity.result.isAdult) ?: listOf()) { chip ->
|
||||
val tag = chip.text.toString()
|
||||
chip.isChecked = selectedTags.contains(tag)
|
||||
chip.isCloseIconVisible = exTags.contains(tag)
|
||||
chip.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (isChecked) {
|
||||
chip.isCloseIconVisible = false
|
||||
exTags.remove(tag)
|
||||
selectedTags.add(tag)
|
||||
} else
|
||||
selectedTags.remove(tag)
|
||||
}
|
||||
chip.setOnLongClickListener {
|
||||
chip.isChecked = false
|
||||
chip.isCloseIconVisible = true
|
||||
exTags.add(tag)
|
||||
}
|
||||
}
|
||||
chip.setOnLongClickListener {
|
||||
chip.isChecked = false
|
||||
chip.isCloseIconVisible = true
|
||||
exTags.add(tag)
|
||||
}
|
||||
}
|
||||
binding.searchTagsGrid.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.searchFilterTags.layoutManager =
|
||||
if (!isChecked) LinearLayoutManager(binding.root.context, HORIZONTAL, false)
|
||||
|
@ -158,10 +163,12 @@ class SearchFilterBottomDialog() : BottomSheetDialogFragment() {
|
|||
|
||||
class FilterChipAdapter(val list: List<String>, private val perform: ((Chip) -> Unit)) :
|
||||
RecyclerView.Adapter<FilterChipAdapter.SearchChipViewHolder>() {
|
||||
inner class SearchChipViewHolder(val binding: ItemChipBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
inner class SearchChipViewHolder(val binding: ItemChipBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchChipViewHolder {
|
||||
val binding = ItemChipBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemChipBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return SearchChipViewHolder(binding)
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ abstract class SourceAdapter(
|
|||
private val scope: CoroutineScope
|
||||
) : RecyclerView.Adapter<SourceAdapter.SourceViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SourceViewHolder {
|
||||
val binding = ItemCharacterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemCharacterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return SourceViewHolder(binding)
|
||||
}
|
||||
|
||||
|
@ -34,7 +35,8 @@ abstract class SourceAdapter(
|
|||
|
||||
abstract suspend fun onItemClick(source: ShowResponse)
|
||||
|
||||
inner class SourceViewHolder(val binding: ItemCharacterBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class SourceViewHolder(val binding: ItemCharacterBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
dialogFragment.dismiss()
|
||||
|
|
|
@ -13,8 +13,8 @@ import androidx.fragment.app.activityViewModels
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.media.anime.AnimeSourceAdapter
|
||||
import ani.dantotsu.databinding.BottomSheetSourceSearchBinding
|
||||
import ani.dantotsu.media.anime.AnimeSourceAdapter
|
||||
import ani.dantotsu.media.manga.MangaSourceAdapter
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
|
@ -38,7 +38,11 @@ class SourceSearchDialogFragment : BottomSheetDialogFragment() {
|
|||
var id: Int? = null
|
||||
var media: Media? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetSourceSearchBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -47,7 +51,8 @@ class SourceSearchDialogFragment : BottomSheetDialogFragment() {
|
|||
binding.mediaListContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin += navBarHeight }
|
||||
|
||||
val scope = requireActivity().lifecycleScope
|
||||
val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
val imm =
|
||||
requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
model.getMedia().observe(viewLifecycleOwner) {
|
||||
media = it
|
||||
if (media != null) {
|
||||
|
@ -65,6 +70,7 @@ class SourceSearchDialogFragment : BottomSheetDialogFragment() {
|
|||
anime = false
|
||||
(if (media!!.isAdult) HMangaSources else MangaSources)[i!!]
|
||||
}
|
||||
|
||||
fun search() {
|
||||
binding.searchBarText.clearFocus()
|
||||
imm.hideSoftInputFromWindow(binding.searchBarText.windowToken, 0)
|
||||
|
@ -86,7 +92,8 @@ class SourceSearchDialogFragment : BottomSheetDialogFragment() {
|
|||
search()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
binding.searchBar.setEndIconOnClickListener { search() }
|
||||
|
@ -101,7 +108,11 @@ class SourceSearchDialogFragment : BottomSheetDialogFragment() {
|
|||
else MangaSourceAdapter(j, model, i!!, media!!.id, this, scope)
|
||||
binding.searchRecyclerView.layoutManager = GridLayoutManager(
|
||||
requireActivity(),
|
||||
clamp(requireActivity().resources.displayMetrics.widthPixels / 124f.px, 1, 4)
|
||||
clamp(
|
||||
requireActivity().resources.displayMetrics.widthPixels / 124f.px,
|
||||
1,
|
||||
4
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,17 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.EmptyAdapter
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.databinding.ActivityStudioBinding
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.initActivity
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.px
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -31,7 +37,7 @@ class StudioActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
LangSet.setLocale(this)
|
||||
ThemeManager(this).applyTheme()
|
||||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityStudioBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
package ani.dantotsu.media
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import ani.dantotsu.parsers.SubtitleType
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.Request
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.FileInputStream
|
||||
|
||||
class SubtitleDownloader {
|
||||
|
||||
|
@ -30,7 +25,7 @@ class SubtitleDownloader {
|
|||
|
||||
// Check if response is successful
|
||||
if (response.isSuccessful) {
|
||||
val responseBody = response.body?.string()
|
||||
val responseBody = response.body.string()
|
||||
|
||||
|
||||
val subtitleType = when {
|
||||
|
|
|
@ -5,8 +5,10 @@ import android.view.ViewGroup
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.databinding.ItemTitleBinding
|
||||
|
||||
class TitleAdapter(private val text: String) : RecyclerView.Adapter<TitleAdapter.TitleViewHolder>() {
|
||||
inner class TitleViewHolder(val binding: ItemTitleBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
class TitleAdapter(private val text: String) :
|
||||
RecyclerView.Adapter<TitleAdapter.TitleViewHolder>() {
|
||||
inner class TitleViewHolder(val binding: ItemTitleBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TitleViewHolder {
|
||||
val binding = ItemTitleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
|
|
|
@ -15,7 +15,7 @@ data class Anime(
|
|||
var ed: ArrayList<String> = arrayListOf(),
|
||||
|
||||
var mainStudio: Studio? = null,
|
||||
var author: Author?=null,
|
||||
var author: Author? = null,
|
||||
|
||||
var youtube: String? = null,
|
||||
var nextAiringEpisode: Int? = null,
|
||||
|
|
|
@ -1,23 +1,17 @@
|
|||
package ani.dantotsu.media.anime
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
|
@ -27,21 +21,11 @@ import ani.dantotsu.media.SourceSearchDialogFragment
|
|||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.DynamicAnimeParser
|
||||
import ani.dantotsu.parsers.WatchSources
|
||||
import ani.dantotsu.settings.ExtensionsActivity
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.lang.IndexOutOfBoundsException
|
||||
|
||||
class AnimeWatchAdapter(
|
||||
private val media: Media,
|
||||
|
@ -72,23 +56,33 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
|
||||
binding.animeSourceDubbed.isChecked = media.selected!!.preferDub
|
||||
binding.animeSourceDubbedText.text = if (media.selected!!.preferDub) currActivity()!!.getString(R.string.dubbed) else currActivity()!!.getString(R.string.subbed)
|
||||
binding.animeSourceDubbedText.text =
|
||||
if (media.selected!!.preferDub) currActivity()!!.getString(R.string.dubbed) else currActivity()!!.getString(
|
||||
R.string.subbed
|
||||
)
|
||||
|
||||
//PreferDub
|
||||
var changing = false
|
||||
binding.animeSourceDubbed.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.animeSourceDubbedText.text = if (isChecked) currActivity()!!.getString(R.string.dubbed) else currActivity()!!.getString(R.string.subbed)
|
||||
binding.animeSourceDubbedText.text =
|
||||
if (isChecked) currActivity()!!.getString(R.string.dubbed) else currActivity()!!.getString(
|
||||
R.string.subbed
|
||||
)
|
||||
if (!changing) fragment.onDubClicked(isChecked)
|
||||
}
|
||||
|
||||
//Wrong Title
|
||||
binding.animeSourceSearch.setOnClickListener {
|
||||
SourceSearchDialogFragment().show(fragment.requireActivity().supportFragmentManager, null)
|
||||
SourceSearchDialogFragment().show(
|
||||
fragment.requireActivity().supportFragmentManager,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
//Source Selection
|
||||
var source = media.selected!!.sourceIndex.let { if (it >= watchSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex,source)
|
||||
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])
|
||||
watchSources[source].apply {
|
||||
|
@ -100,7 +94,13 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
binding.animeSource.setAdapter(ArrayAdapter(fragment.requireContext(), R.layout.item_dropdown, watchSources.names))
|
||||
binding.animeSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
watchSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSourceTitle.isSelected = true
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i).apply {
|
||||
|
@ -109,9 +109,10 @@ class AnimeWatchAdapter(
|
|||
changing = true
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
binding.animeSourceDubbedCont.visibility = if (isDubAvailableSeparately) View.VISIBLE else View.GONE
|
||||
binding.animeSourceDubbedCont.visibility =
|
||||
if (isDubAvailableSeparately) View.VISIBLE else View.GONE
|
||||
source = i
|
||||
setLanguageList(0,i)
|
||||
setLanguageList(0, i)
|
||||
}
|
||||
subscribeButton(false)
|
||||
fragment.loadEpisodes(i, false)
|
||||
|
@ -124,11 +125,13 @@ class AnimeWatchAdapter(
|
|||
fragment.onLangChange(i)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
changing = true
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
binding.animeSourceDubbedCont.visibility = if (isDubAvailableSeparately) View.VISIBLE else View.GONE
|
||||
binding.animeSourceDubbedCont.visibility =
|
||||
if (isDubAvailableSeparately) View.VISIBLE else View.GONE
|
||||
setLanguageList(i, source)
|
||||
}
|
||||
subscribeButton(false)
|
||||
|
@ -146,7 +149,7 @@ class AnimeWatchAdapter(
|
|||
|
||||
|
||||
//Subscription
|
||||
subscribe = MediaDetailsActivity.PopImageButton(
|
||||
subscribe = MediaDetailsActivity.PopImageButton(
|
||||
fragment.lifecycleScope,
|
||||
binding.animeSourceSubscribe,
|
||||
R.drawable.ic_round_notifications_active_24,
|
||||
|
@ -161,7 +164,7 @@ class AnimeWatchAdapter(
|
|||
subscribeButton(false)
|
||||
|
||||
binding.animeSourceSubscribe.setOnLongClickListener {
|
||||
openSettings(fragment.requireContext(),getChannelId(true,media.id))
|
||||
openSettings(fragment.requireContext(), getChannelId(true, media.id))
|
||||
}
|
||||
|
||||
//Icons
|
||||
|
@ -200,12 +203,12 @@ class AnimeWatchAdapter(
|
|||
style = 2
|
||||
fragment.onIconPressed(style, reversed)
|
||||
}
|
||||
binding.animeScanlatorTop.visibility= View.GONE
|
||||
binding.animeScanlatorTop.visibility = View.GONE
|
||||
//Episode Handling
|
||||
handleEpisodes()
|
||||
}
|
||||
|
||||
fun subscribeButton(enabled : Boolean) {
|
||||
fun subscribeButton(enabled: Boolean) {
|
||||
subscribe?.enabled(enabled)
|
||||
}
|
||||
|
||||
|
@ -219,14 +222,26 @@ class AnimeWatchAdapter(
|
|||
for (position in arr.indices) {
|
||||
val last = if (position + 1 == arr.size) names.size else (limit * (position + 1))
|
||||
val chip =
|
||||
ItemChipBinding.inflate(LayoutInflater.from(fragment.context), binding.animeSourceChipGroup, false).root
|
||||
ItemChipBinding.inflate(
|
||||
LayoutInflater.from(fragment.context),
|
||||
binding.animeSourceChipGroup,
|
||||
false
|
||||
).root
|
||||
chip.isCheckable = true
|
||||
fun selected() {
|
||||
chip.isChecked = true
|
||||
binding.animeWatchChipScroll.smoothScrollTo((chip.left - screenWidth / 2) + (chip.width / 2), 0)
|
||||
binding.animeWatchChipScroll.smoothScrollTo(
|
||||
(chip.left - screenWidth / 2) + (chip.width / 2),
|
||||
0
|
||||
)
|
||||
}
|
||||
chip.text = "${names[limit * (position)]} - ${names[last - 1]}"
|
||||
chip.setTextColor(ContextCompat.getColorStateList(fragment.requireContext(), R.color.chip_text_color))
|
||||
chip.setTextColor(
|
||||
ContextCompat.getColorStateList(
|
||||
fragment.requireContext(),
|
||||
R.color.chip_text_color
|
||||
)
|
||||
)
|
||||
|
||||
chip.setOnClickListener {
|
||||
selected()
|
||||
|
@ -239,7 +254,14 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
}
|
||||
if (select != null)
|
||||
binding.animeWatchChipScroll.apply { post { scrollTo((select.left - screenWidth / 2) + (select.width / 2), 0) } }
|
||||
binding.animeWatchChipScroll.apply {
|
||||
post {
|
||||
scrollTo(
|
||||
(select.left - screenWidth / 2) + (select.width / 2),
|
||||
0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +303,9 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
}
|
||||
val ep = media.anime.episodes!![continueEp]!!
|
||||
binding.itemEpisodeImage.loadImage(ep.thumb ?: FileUrl[media.banner ?: media.cover], 0)
|
||||
binding.itemEpisodeImage.loadImage(
|
||||
ep.thumb ?: FileUrl[media.banner ?: media.cover], 0
|
||||
)
|
||||
if (ep.filler) binding.itemEpisodeFillerView.visibility = View.VISIBLE
|
||||
binding.animeSourceContinueText.text =
|
||||
currActivity()!!.getString(R.string.continue_episode) + "${ep.number}${if (ep.filler) " - Filler" else ""}${if (ep.title != null) "\n${ep.title}" else ""}"
|
||||
|
@ -321,10 +345,17 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
}catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources.firstOrNull()?.lang ?: "Unknown")
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(
|
||||
parser.extension.sources.firstOrNull()?.lang ?: "Unknown"
|
||||
)
|
||||
}
|
||||
binding?.animeSourceLanguage?.setAdapter(ArrayAdapter(fragment.requireContext(), R.layout.item_dropdown, parser.extension.sources.map { it.lang }))
|
||||
binding?.animeSourceLanguage?.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
parser.extension.sources.map { it.lang })
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +363,8 @@ class AnimeWatchAdapter(
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
//Timer
|
||||
countDown(media, binding.animeSourceContainer)
|
||||
|
|
|
@ -8,8 +8,6 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.math.MathUtils
|
||||
|
@ -28,8 +26,6 @@ import ani.dantotsu.media.MediaDetailsViewModel
|
|||
import ani.dantotsu.parsers.AnimeParser
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.HAnimeSources
|
||||
import ani.dantotsu.settings.ExtensionsActivity
|
||||
import ani.dantotsu.settings.InstalledAnimeExtensionsFragment
|
||||
import ani.dantotsu.settings.PlayerSettings
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
|
@ -40,17 +36,12 @@ import ani.dantotsu.subcriptions.SubscriptionHelper
|
|||
import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.navigationrail.NavigationRailView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -96,8 +87,10 @@ class AnimeWatchFragment : Fragment() {
|
|||
maxGridSize = max(4, maxGridSize - (maxGridSize % 2))
|
||||
|
||||
playerSettings =
|
||||
loadData("player_settings", toast = false) ?: PlayerSettings().apply { saveData("player_settings", this) }
|
||||
uiSettings = loadData("ui_settings", toast = false) ?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
|
||||
loadData("player_settings", toast = false)
|
||||
?: PlayerSettings().apply { saveData("player_settings", this) }
|
||||
uiSettings = loadData("ui_settings", toast = false)
|
||||
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
|
||||
|
||||
val gridLayoutManager = GridLayoutManager(requireContext(), maxGridSize)
|
||||
|
||||
|
@ -106,11 +99,11 @@ class AnimeWatchFragment : Fragment() {
|
|||
val style = episodeAdapter.getItemViewType(position)
|
||||
|
||||
return when (position) {
|
||||
0 -> maxGridSize
|
||||
0 -> maxGridSize
|
||||
else -> when (style) {
|
||||
0 -> maxGridSize
|
||||
1 -> 2
|
||||
2 -> 1
|
||||
0 -> maxGridSize
|
||||
1 -> 2
|
||||
2 -> 1
|
||||
else -> maxGridSize
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +122,8 @@ class AnimeWatchFragment : Fragment() {
|
|||
media = it
|
||||
media.selected = model.loadSelected(media)
|
||||
|
||||
subscribed = SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id)
|
||||
subscribed =
|
||||
SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id)
|
||||
|
||||
style = media.selected!!.recyclerStyle
|
||||
reverse = media.selected!!.recyclerReversed
|
||||
|
@ -141,9 +135,11 @@ class AnimeWatchFragment : Fragment() {
|
|||
model.watchSources = if (media.isAdult) HAnimeSources else AnimeSources
|
||||
|
||||
headerAdapter = AnimeWatchAdapter(it, this, model.watchSources!!)
|
||||
episodeAdapter = EpisodeAdapter(style ?: uiSettings.animeDefaultView, media, this)
|
||||
episodeAdapter =
|
||||
EpisodeAdapter(style ?: uiSettings.animeDefaultView, media, this)
|
||||
|
||||
binding.animeSourceRecycler.adapter = ConcatAdapter(headerAdapter, episodeAdapter)
|
||||
binding.animeSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, episodeAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
awaitAll(
|
||||
|
@ -165,15 +161,20 @@ class AnimeWatchFragment : Fragment() {
|
|||
episodes.forEach { (i, episode) ->
|
||||
if (media.anime?.fillerEpisodes != null) {
|
||||
if (media.anime!!.fillerEpisodes!!.containsKey(i)) {
|
||||
episode.title = episode.title ?: media.anime!!.fillerEpisodes!![i]?.title
|
||||
episode.title =
|
||||
episode.title ?: media.anime!!.fillerEpisodes!![i]?.title
|
||||
episode.filler = media.anime!!.fillerEpisodes!![i]?.filler ?: false
|
||||
}
|
||||
}
|
||||
if (media.anime?.kitsuEpisodes != null) {
|
||||
if (media.anime!!.kitsuEpisodes!!.containsKey(i)) {
|
||||
episode.desc = episode.desc ?: media.anime!!.kitsuEpisodes!![i]?.desc
|
||||
episode.title = episode.title ?: media.anime!!.kitsuEpisodes!![i]?.title
|
||||
episode.thumb = episode.thumb ?: media.anime!!.kitsuEpisodes!![i]?.thumb ?: FileUrl[media.cover]
|
||||
episode.desc =
|
||||
episode.desc ?: media.anime!!.kitsuEpisodes!![i]?.desc
|
||||
episode.title =
|
||||
episode.title ?: media.anime!!.kitsuEpisodes!![i]?.title
|
||||
episode.thumb =
|
||||
episode.thumb ?: media.anime!!.kitsuEpisodes!![i]?.thumb
|
||||
?: FileUrl[media.cover]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +188,7 @@ class AnimeWatchFragment : Fragment() {
|
|||
val limit = when {
|
||||
(divisions < 25) -> 25
|
||||
(divisions < 50) -> 50
|
||||
else -> 100
|
||||
else -> 100
|
||||
}
|
||||
headerAdapter.clearChips()
|
||||
if (total > limit) {
|
||||
|
@ -247,7 +248,12 @@ class AnimeWatchFragment : Fragment() {
|
|||
selected.preferDub = checked
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
media.selected = selected
|
||||
lifecycleScope.launch(Dispatchers.IO) { model.forceLoadEpisode(media, selected.sourceIndex) }
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
model.forceLoadEpisode(
|
||||
media,
|
||||
selected.sourceIndex
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun loadEpisodes(i: Int, invalidate: Boolean) {
|
||||
|
@ -289,7 +295,8 @@ class AnimeWatchFragment : Fragment() {
|
|||
else getString(R.string.unsubscribed_notification)
|
||||
)
|
||||
}
|
||||
fun openSettings(pkg: AnimeExtension.Installed){
|
||||
|
||||
fun openSettings(pkg: AnimeExtension.Installed) {
|
||||
val changeUIVisibility: (Boolean) -> Unit = { show ->
|
||||
val activity = requireActivity() as MediaDetailsActivity
|
||||
val visibility = if (show) View.VISIBLE else View.GONE
|
||||
|
@ -297,9 +304,9 @@ class AnimeWatchFragment : Fragment() {
|
|||
activity.findViewById<ViewPager2>(R.id.mediaViewPager).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaCover).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaClose).visibility = visibility
|
||||
try{
|
||||
try {
|
||||
activity.findViewById<CustomBottomNavBar>(R.id.mediaTab).visibility = visibility
|
||||
}catch (e: ClassCastException){
|
||||
} catch (e: ClassCastException) {
|
||||
activity.findViewById<NavigationRailView>(R.id.mediaTab).visibility = visibility
|
||||
}
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
|
||||
|
@ -363,46 +370,46 @@ class AnimeWatchFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
fun onEpisodeClick(i: String) {
|
||||
model.continueMedia = false
|
||||
model.saveSelected(media.id, media.selected!!, requireActivity())
|
||||
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager)
|
||||
fun onEpisodeClick(i: String) {
|
||||
model.continueMedia = false
|
||||
model.saveSelected(media.id, media.selected!!, requireActivity())
|
||||
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager)
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest episode for subscription
|
||||
selected.latest =
|
||||
media.anime?.episodes?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
||||
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
headerAdapter.handleEpisodes()
|
||||
episodeAdapter.notifyItemRangeRemoved(0, episodeAdapter.arr.size)
|
||||
var arr: ArrayList<Episode> = arrayListOf()
|
||||
if (media.anime!!.episodes != null) {
|
||||
val end = if (end != null && end!! < media.anime!!.episodes!!.size) end else null
|
||||
arr.addAll(
|
||||
media.anime!!.episodes!!.values.toList()
|
||||
.slice(start..(end ?: (media.anime!!.episodes!!.size - 1)))
|
||||
)
|
||||
if (reverse)
|
||||
arr = (arr.reversed() as? ArrayList<Episode>) ?: arr
|
||||
}
|
||||
episodeAdapter.arr = arr
|
||||
episodeAdapter.updateType(style ?: uiSettings.animeDefaultView)
|
||||
episodeAdapter.notifyItemRangeInserted(0, arr.size)
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
override fun onDestroy() {
|
||||
model.watchSources?.flushText()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
//Find latest episode for subscription
|
||||
selected.latest =
|
||||
media.anime?.episodes?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
||||
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
headerAdapter.handleEpisodes()
|
||||
episodeAdapter.notifyItemRangeRemoved(0, episodeAdapter.arr.size)
|
||||
var arr: ArrayList<Episode> = arrayListOf()
|
||||
if (media.anime!!.episodes != null) {
|
||||
val end = if (end != null && end!! < media.anime!!.episodes!!.size) end else null
|
||||
arr.addAll(
|
||||
media.anime!!.episodes!!.values.toList()
|
||||
.slice(start..(end ?: (media.anime!!.episodes!!.size - 1)))
|
||||
)
|
||||
if (reverse)
|
||||
arr = (arr.reversed() as? ArrayList<Episode>) ?: arr
|
||||
}
|
||||
episodeAdapter.arr = arr
|
||||
episodeAdapter.updateType(style ?: uiSettings.animeDefaultView)
|
||||
episodeAdapter.notifyItemRangeInserted(0, arr.size)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
model.watchSources?.flushText()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
var state: Parcelable? = null
|
||||
var state: Parcelable? = null
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
|
|
|
@ -14,12 +14,12 @@ data class Episode(
|
|||
var selectedExtractor: String? = null,
|
||||
var selectedVideo: Int = 0,
|
||||
var selectedSubtitle: Int? = -1,
|
||||
var extractors: MutableList<VideoExtractor>?=null,
|
||||
@Transient var extractorCallback: ((VideoExtractor) -> Unit)?=null,
|
||||
var extractors: MutableList<VideoExtractor>? = null,
|
||||
@Transient var extractorCallback: ((VideoExtractor) -> Unit)? = null,
|
||||
var allStreams: Boolean = false,
|
||||
var watched: Long? = null,
|
||||
var maxLength: Long? = null,
|
||||
val extra: Map<String,String>?=null,
|
||||
val extra: Map<String, String>? = null,
|
||||
val sEpisode: eu.kanade.tachiyomi.animesource.model.SEpisode? = null
|
||||
) : Serializable
|
||||
|
||||
|
|
|
@ -41,15 +41,30 @@ class EpisodeAdapter(
|
|||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return (when (viewType) {
|
||||
0 -> EpisodeListViewHolder(ItemEpisodeListBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
1 -> EpisodeGridViewHolder(ItemEpisodeGridBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
2 -> EpisodeCompactViewHolder(
|
||||
0 -> EpisodeListViewHolder(
|
||||
ItemEpisodeListBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
1 -> EpisodeGridViewHolder(
|
||||
ItemEpisodeGridBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
2 -> EpisodeCompactViewHolder(
|
||||
ItemEpisodeCompactBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException()
|
||||
})
|
||||
}
|
||||
|
@ -62,15 +77,21 @@ class EpisodeAdapter(
|
|||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val ep = arr[position]
|
||||
val title =
|
||||
"${if (!ep.title.isNullOrEmpty() && ep.title != "null") "" else currContext()!!.getString(R.string.episode_singular)} ${if (!ep.title.isNullOrEmpty() && ep.title != "null") ep.title else ep.number}"
|
||||
"${
|
||||
if (!ep.title.isNullOrEmpty() && ep.title != "null") "" else currContext()!!.getString(
|
||||
R.string.episode_singular
|
||||
)
|
||||
} ${if (!ep.title.isNullOrEmpty() && ep.title != "null") ep.title else ep.number}"
|
||||
|
||||
when (holder) {
|
||||
is EpisodeListViewHolder -> {
|
||||
is EpisodeListViewHolder -> {
|
||||
val binding = holder.binding
|
||||
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
|
||||
|
||||
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)
|
||||
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)
|
||||
binding.itemEpisodeNumber.text = ep.number
|
||||
binding.itemEpisodeTitle.text = title
|
||||
|
||||
|
@ -81,7 +102,8 @@ class EpisodeAdapter(
|
|||
binding.itemEpisodeFiller.visibility = View.GONE
|
||||
binding.itemEpisodeFillerView.visibility = View.GONE
|
||||
}
|
||||
binding.itemEpisodeDesc.visibility = if (ep.desc != null && ep.desc?.trim(' ') != "") View.VISIBLE else View.GONE
|
||||
binding.itemEpisodeDesc.visibility =
|
||||
if (ep.desc != null && ep.desc?.trim(' ') != "") View.VISIBLE else View.GONE
|
||||
binding.itemEpisodeDesc.text = ep.desc ?: ""
|
||||
|
||||
if (media.userProgress != null) {
|
||||
|
@ -110,12 +132,14 @@ class EpisodeAdapter(
|
|||
)
|
||||
}
|
||||
|
||||
is EpisodeGridViewHolder -> {
|
||||
is EpisodeGridViewHolder -> {
|
||||
val binding = holder.binding
|
||||
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
binding.itemEpisodeNumber.text = ep.number
|
||||
binding.itemEpisodeTitle.text = title
|
||||
|
@ -155,7 +179,8 @@ class EpisodeAdapter(
|
|||
val binding = holder.binding
|
||||
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
|
||||
binding.itemEpisodeNumber.text = ep.number
|
||||
binding.itemEpisodeFillerView.visibility = if (ep.filler) View.VISIBLE else View.GONE
|
||||
binding.itemEpisodeFillerView.visibility =
|
||||
if (ep.filler) View.VISIBLE else View.GONE
|
||||
if (media.userProgress != null) {
|
||||
if ((ep.number.toFloatOrNull() ?: 9999f) <= media.userProgress!!.toFloat())
|
||||
binding.itemEpisodeViewedCover.visibility = View.VISIBLE
|
||||
|
@ -180,7 +205,8 @@ class EpisodeAdapter(
|
|||
|
||||
override fun getItemCount(): Int = arr.size
|
||||
|
||||
inner class EpisodeCompactViewHolder(val binding: ItemEpisodeCompactBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class EpisodeCompactViewHolder(val binding: ItemEpisodeCompactBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
if (bindingAdapterPosition < arr.size && bindingAdapterPosition >= 0)
|
||||
|
@ -189,7 +215,8 @@ class EpisodeAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
inner class EpisodeGridViewHolder(val binding: ItemEpisodeGridBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class EpisodeGridViewHolder(val binding: ItemEpisodeGridBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
if (bindingAdapterPosition < arr.size && bindingAdapterPosition >= 0)
|
||||
|
@ -198,7 +225,8 @@ class EpisodeAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
inner class EpisodeListViewHolder(val binding: ItemEpisodeListBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
inner class EpisodeListViewHolder(val binding: ItemEpisodeListBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
if (bindingAdapterPosition < arr.size && bindingAdapterPosition >= 0)
|
||||
|
|
|
@ -17,7 +17,6 @@ import android.graphics.drawable.Animatable
|
|||
import android.hardware.SensorManager
|
||||
import android.media.AudioManager
|
||||
import android.media.AudioManager.*
|
||||
import android.media.PlaybackParams
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -74,6 +73,7 @@ import ani.dantotsu.media.SubtitleDownloader
|
|||
import ani.dantotsu.others.AniSkip
|
||||
import ani.dantotsu.others.AniSkip.getType
|
||||
import ani.dantotsu.others.Download.download
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.others.ResettableTimer
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.parsers.*
|
||||
|
@ -81,7 +81,6 @@ import ani.dantotsu.settings.PlayerSettings
|
|||
import ani.dantotsu.settings.PlayerSettingsActivity
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
@ -1325,7 +1324,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
|
|||
.setAllowMultipleAdaptiveSelections(true)
|
||||
.setPreferredTextLanguage(subtitle?.language ?: "en")
|
||||
.setPreferredTextRoleFlags(C.ROLE_FLAG_SUBTITLE)
|
||||
.setRendererDisabled(C.TRACK_TYPE_VIDEO, false)
|
||||
.setRendererDisabled(TRACK_TYPE_VIDEO, false)
|
||||
.setRendererDisabled(C.TRACK_TYPE_AUDIO, false)
|
||||
.setRendererDisabled(C.TRACK_TYPE_TEXT, false)
|
||||
.setMinVideoSize(
|
||||
|
|
|
@ -25,8 +25,6 @@ import ani.dantotsu.media.MediaDetailsViewModel
|
|||
import ani.dantotsu.others.Download.download
|
||||
import ani.dantotsu.parsers.VideoExtractor
|
||||
import ani.dantotsu.parsers.VideoType
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -54,7 +52,11 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetSelectorBinding.inflate(inflater, container, false)
|
||||
val window = dialog?.window
|
||||
window?.statusBarColor = Color.TRANSPARENT
|
||||
|
@ -71,7 +73,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
media = m
|
||||
if (media != null && !loaded) {
|
||||
loaded = true
|
||||
val ep = media?.anime?.episodes?.get(media?.anime?.selectedEpisode)
|
||||
val ep = media?.anime?.episodes?.get(media?.anime?.selectedEpisode)
|
||||
episode = ep
|
||||
if (ep != null) {
|
||||
|
||||
|
@ -92,14 +94,17 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
fun load() {
|
||||
val size = ep.extractors?.find { it.server.name == selected }?.videos?.size
|
||||
if (size!=null && size >= media!!.selected!!.video) {
|
||||
media!!.anime!!.episodes?.get(media!!.anime!!.selectedEpisode!!)?.selectedExtractor = selected
|
||||
media!!.anime!!.episodes?.get(media!!.anime!!.selectedEpisode!!)?.selectedVideo = media!!.selected!!.video
|
||||
val size =
|
||||
ep.extractors?.find { it.server.name == selected }?.videos?.size
|
||||
if (size != null && size >= media!!.selected!!.video) {
|
||||
media!!.anime!!.episodes?.get(media!!.anime!!.selectedEpisode!!)?.selectedExtractor =
|
||||
selected
|
||||
media!!.anime!!.episodes?.get(media!!.anime!!.selectedEpisode!!)?.selectedVideo =
|
||||
media!!.selected!!.video
|
||||
startExoplayer(media!!)
|
||||
} else fail()
|
||||
}
|
||||
|
||||
|
||||
if (ep.extractors.isNullOrEmpty()) {
|
||||
model.getEpisode().observe(this) {
|
||||
if (it != null) {
|
||||
|
@ -116,8 +121,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}) fail()
|
||||
}
|
||||
} else load()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
binding.selectorRecyclerView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
bottomMargin = navBarHeight
|
||||
}
|
||||
|
@ -130,10 +134,14 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
saveData("make_default", makeDefault)
|
||||
}
|
||||
binding.selectorRecyclerView.layoutManager =
|
||||
LinearLayoutManager(requireActivity(), LinearLayoutManager.VERTICAL, false)
|
||||
LinearLayoutManager(
|
||||
requireActivity(),
|
||||
LinearLayoutManager.VERTICAL,
|
||||
false
|
||||
)
|
||||
val adapter = ExtractorAdapter()
|
||||
binding.selectorRecyclerView.adapter = adapter
|
||||
if (!ep.allStreams ) {
|
||||
if (!ep.allStreams) {
|
||||
ep.extractorCallback = {
|
||||
scope.launch {
|
||||
adapter.add(it)
|
||||
|
@ -141,12 +149,15 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
model.getEpisode().observe(this) {
|
||||
if (it != null) {
|
||||
media!!.anime?.episodes?.set(media!!.anime?.selectedEpisode!!, ep)
|
||||
media!!.anime?.episodes?.set(
|
||||
media!!.anime?.selectedEpisode!!,
|
||||
ep
|
||||
)
|
||||
}
|
||||
}
|
||||
scope.launch(Dispatchers.IO) {
|
||||
model.loadEpisodeVideos(ep, media!!.selected!!.sourceIndex)
|
||||
withContext(Dispatchers.Main){
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.selectorProgressBar.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +186,10 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
ExoplayerView.initialized = true
|
||||
startActivity(intent)
|
||||
} else {
|
||||
model.setEpisode(media.anime!!.episodes!![media.anime.selectedEpisode!!]!!, "startExo no launch")
|
||||
model.setEpisode(
|
||||
media.anime!!.episodes!![media.anime.selectedEpisode!!]!!,
|
||||
"startExo no launch"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,54 +200,72 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private inner class ExtractorAdapter : RecyclerView.Adapter<ExtractorAdapter.StreamViewHolder>() {
|
||||
private inner class ExtractorAdapter :
|
||||
RecyclerView.Adapter<ExtractorAdapter.StreamViewHolder>() {
|
||||
val links = mutableListOf<VideoExtractor>()
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StreamViewHolder =
|
||||
StreamViewHolder(ItemStreamBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
StreamViewHolder(
|
||||
ItemStreamBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: StreamViewHolder, position: Int) {
|
||||
val extractor = links[position]
|
||||
holder.binding.streamName.text = extractor.server.name
|
||||
|
||||
holder.binding.streamRecyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
holder.binding.streamRecyclerView.adapter = VideoAdapter(extractor)
|
||||
holder.binding.streamRecyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
holder.binding.streamRecyclerView.adapter = VideoAdapter(extractor)
|
||||
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = links.size
|
||||
|
||||
fun add(videoExtractor: VideoExtractor){
|
||||
if(videoExtractor.videos.isNotEmpty()) {
|
||||
fun add(videoExtractor: VideoExtractor) {
|
||||
if (videoExtractor.videos.isNotEmpty()) {
|
||||
links.add(videoExtractor)
|
||||
notifyItemInserted(links.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun addAll(extractors: List<VideoExtractor>?) {
|
||||
links.addAll(extractors?:return)
|
||||
notifyItemRangeInserted(0,extractors.size)
|
||||
links.addAll(extractors ?: return)
|
||||
notifyItemRangeInserted(0, extractors.size)
|
||||
}
|
||||
|
||||
private inner class StreamViewHolder(val binding: ItemStreamBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
private inner class StreamViewHolder(val binding: ItemStreamBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
|
||||
private inner class VideoAdapter(private val extractor : VideoExtractor) : RecyclerView.Adapter<VideoAdapter.UrlViewHolder>() {
|
||||
private inner class VideoAdapter(private val extractor: VideoExtractor) :
|
||||
RecyclerView.Adapter<VideoAdapter.UrlViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UrlViewHolder {
|
||||
return UrlViewHolder(ItemUrlBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
return UrlViewHolder(
|
||||
ItemUrlBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: UrlViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
val video = extractor.videos[position]
|
||||
binding.urlQuality.text = if(video.quality!=null) "${video.quality}p" else "Default Quality"
|
||||
binding.urlQuality.text =
|
||||
if (video.quality != null) "${video.quality}p" else "Default Quality"
|
||||
binding.urlNote.text = video.extraNote ?: ""
|
||||
binding.urlNote.visibility = if (video.extraNote != null) View.VISIBLE else View.GONE
|
||||
binding.urlDownload.visibility = View.VISIBLE
|
||||
binding.urlDownload.setSafeOnClickListener {
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.selectedExtractor = extractor.server.name
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.selectedVideo = position
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.selectedExtractor =
|
||||
extractor.server.name
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]!!.selectedVideo =
|
||||
position
|
||||
binding.urlDownload.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
download(
|
||||
requireActivity(),
|
||||
|
@ -245,10 +277,11 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
if (video.format == VideoType.CONTAINER) {
|
||||
binding.urlSize.visibility = if (video.size != null) View.VISIBLE else View.GONE
|
||||
binding.urlSize.text =
|
||||
// if video size is null or 0, show "Unknown Size" else show the size in MB
|
||||
(if (video.extraNote != null) " : " else "") + (if (video.size == 0.0) "Unknown Size" else (DecimalFormat("#.##").format(video.size ?: 0).toString()+ " MB"))
|
||||
}
|
||||
else {
|
||||
// if video size is null or 0, show "Unknown Size" else show the size in MB
|
||||
(if (video.extraNote != null) " : " else "") + (if (video.size == 0.0) "Unknown Size" else (DecimalFormat(
|
||||
"#.##"
|
||||
).format(video.size ?: 0).toString() + " MB"))
|
||||
} else {
|
||||
binding.urlQuality.text = "Multi Quality"
|
||||
if ((loadData<Int>("settings_download_manager") ?: 0) == 0) {
|
||||
binding.urlDownload.visibility = View.GONE
|
||||
|
@ -258,12 +291,15 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
|
||||
override fun getItemCount(): Int = extractor.videos.size
|
||||
|
||||
private inner class UrlViewHolder(val binding: ItemUrlBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
private inner class UrlViewHolder(val binding: ItemUrlBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
itemView.setSafeOnClickListener {
|
||||
tryWith(true) {
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]?.selectedExtractor = extractor.server.name
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]?.selectedVideo = bindingAdapterPosition
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]?.selectedExtractor =
|
||||
extractor.server.name
|
||||
media!!.anime!!.episodes!![media!!.anime!!.selectedEpisode!!]?.selectedVideo =
|
||||
bindingAdapterPosition
|
||||
if (makeDefault) {
|
||||
media!!.selected!!.server = extractor.server.name
|
||||
media!!.selected!!.video = bindingAdapterPosition
|
||||
|
@ -274,12 +310,12 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
itemView.setOnLongClickListener {
|
||||
val video = extractor.videos[bindingAdapterPosition]
|
||||
val intent= Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(Uri.parse(video.file.url),"video/*")
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(Uri.parse(video.file.url), "video/*")
|
||||
}
|
||||
copyToClipboard(video.file.url,true)
|
||||
copyToClipboard(video.file.url, true)
|
||||
dismiss()
|
||||
startActivity(Intent.createChooser(intent,"Open Video in :"))
|
||||
startActivity(Intent.createChooser(intent, "Open Video in :"))
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -287,7 +323,11 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(server: String? = null, la: Boolean = true, prev: String? = null): SelectorDialogFragment =
|
||||
fun newInstance(
|
||||
server: String? = null,
|
||||
la: Boolean = true,
|
||||
prev: String? = null
|
||||
): SelectorDialogFragment =
|
||||
SelectorDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString("server", server)
|
||||
|
|
|
@ -24,7 +24,11 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
|
|||
val model: MediaDetailsViewModel by activityViewModels()
|
||||
private lateinit var episode: Episode
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetSubtitlesBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -34,17 +38,27 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
|
|||
|
||||
model.getMedia().observe(viewLifecycleOwner) { media ->
|
||||
episode = media?.anime?.episodes?.get(media.anime.selectedEpisode) ?: return@observe
|
||||
val currentExtractor = episode.extractors?.find { it.server.name == episode.selectedExtractor } ?: return@observe
|
||||
val currentExtractor =
|
||||
episode.extractors?.find { it.server.name == episode.selectedExtractor }
|
||||
?: return@observe
|
||||
binding.subtitlesRecycler.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.subtitlesRecycler.adapter = SubtitleAdapter(currentExtractor.subtitles)
|
||||
}
|
||||
}
|
||||
|
||||
inner class SubtitleAdapter(val subtitles: List<Subtitle>) : RecyclerView.Adapter<SubtitleAdapter.StreamViewHolder>() {
|
||||
inner class StreamViewHolder(val binding: ItemSubtitleTextBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
inner class SubtitleAdapter(val subtitles: List<Subtitle>) :
|
||||
RecyclerView.Adapter<SubtitleAdapter.StreamViewHolder>() {
|
||||
inner class StreamViewHolder(val binding: ItemSubtitleTextBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StreamViewHolder =
|
||||
StreamViewHolder(ItemSubtitleTextBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
StreamViewHolder(
|
||||
ItemSubtitleTextBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: StreamViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
|
@ -60,7 +74,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
|
|||
binding.root.setOnClickListener {
|
||||
episode.selectedSubtitle = null
|
||||
model.setEpisode(episode, "Subtitle")
|
||||
model.getMedia().observe(viewLifecycleOwner){media ->
|
||||
model.getMedia().observe(viewLifecycleOwner) { media ->
|
||||
val mediaID: Int = media.id
|
||||
saveData("subLang_${mediaID}", "None", activity)
|
||||
}
|
||||
|
@ -87,7 +101,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
|
|||
"pl-PL" -> "[pl-PL] Polish"
|
||||
"ro-RO" -> "[ro-RO] Romanian"
|
||||
"sv-SE" -> "[sv-SE] Swedish"
|
||||
else -> if(subtitles[position - 1].language matches Regex("([a-z]{2})-([A-Z]{2}|\\d{3})")) "[${subtitles[position - 1].language}]" else subtitles[position - 1].language
|
||||
else -> if (subtitles[position - 1].language matches Regex("([a-z]{2})-([A-Z]{2}|\\d{3})")) "[${subtitles[position - 1].language}]" else subtitles[position - 1].language
|
||||
}
|
||||
model.getMedia().observe(viewLifecycleOwner) { media ->
|
||||
val mediaID: Int = media.id
|
||||
|
@ -100,7 +114,7 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
|
|||
binding.root.setOnClickListener {
|
||||
episode.selectedSubtitle = position - 1
|
||||
model.setEpisode(episode, "Subtitle")
|
||||
model.getMedia().observe(viewLifecycleOwner){media ->
|
||||
model.getMedia().observe(viewLifecycleOwner) { media ->
|
||||
val mediaID: Int = media.id
|
||||
saveData("subLang_${mediaID}", subtitles[position - 1].language, activity)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,10 @@ object VideoCache {
|
|||
val databaseProvider = StandaloneDatabaseProvider(context)
|
||||
if (simpleCache == null)
|
||||
simpleCache = SimpleCache(
|
||||
File(context.cacheDir, "exoplayer").also { it.deleteOnExit() }, // Ensures always fresh file
|
||||
File(
|
||||
context.cacheDir,
|
||||
"exoplayer"
|
||||
).also { it.deleteOnExit() }, // Ensures always fresh file
|
||||
LeastRecentlyUsedCacheEvictor(300L * 1024L * 1024L),
|
||||
databaseProvider
|
||||
)
|
||||
|
|
|
@ -8,5 +8,5 @@ data class Manga(
|
|||
var selectedChapter: String? = null,
|
||||
var chapters: MutableMap<String, MangaChapter>? = null,
|
||||
var slug: String? = null,
|
||||
var author: Author?=null,
|
||||
var author: Author? = null,
|
||||
) : Serializable
|
|
@ -10,7 +10,6 @@ import android.os.Build
|
|||
import android.os.Environment
|
||||
import android.provider.MediaStore
|
||||
import android.util.LruCache
|
||||
import android.widget.Toast
|
||||
import ani.dantotsu.logger
|
||||
import ani.dantotsu.snackString
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
|
@ -23,8 +22,12 @@ import java.io.FileOutputStream
|
|||
data class ImageData(
|
||||
val page: Page,
|
||||
val source: HttpSource
|
||||
){
|
||||
suspend fun fetchAndProcessImage(page: Page, httpSource: HttpSource, context: Context): Bitmap? {
|
||||
) {
|
||||
suspend fun fetchAndProcessImage(
|
||||
page: Page,
|
||||
httpSource: HttpSource,
|
||||
context: Context
|
||||
): Bitmap? {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
// Fetch the image
|
||||
|
@ -52,16 +55,26 @@ data class ImageData(
|
|||
}
|
||||
}
|
||||
|
||||
fun saveImage(bitmap: Bitmap, contentResolver: ContentResolver, filename: String, format: Bitmap.CompressFormat, quality: Int) {
|
||||
fun saveImage(
|
||||
bitmap: Bitmap,
|
||||
contentResolver: ContentResolver,
|
||||
filename: String,
|
||||
format: Bitmap.CompressFormat,
|
||||
quality: Int
|
||||
) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
val contentValues = ContentValues().apply {
|
||||
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
|
||||
put(MediaStore.MediaColumns.MIME_TYPE, "image/${format.name.lowercase()}")
|
||||
put(MediaStore.MediaColumns.RELATIVE_PATH, "${Environment.DIRECTORY_DOWNLOADS}/Dantotsu/Manga")
|
||||
put(
|
||||
MediaStore.MediaColumns.RELATIVE_PATH,
|
||||
"${Environment.DIRECTORY_DOWNLOADS}/Dantotsu/Manga"
|
||||
)
|
||||
}
|
||||
|
||||
val uri: Uri? = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
|
||||
val uri: Uri? =
|
||||
contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
|
||||
|
||||
uri?.let {
|
||||
contentResolver.openOutputStream(it)?.use { os ->
|
||||
|
@ -69,7 +82,8 @@ fun saveImage(bitmap: Bitmap, contentResolver: ContentResolver, filename: String
|
|||
}
|
||||
}
|
||||
} else {
|
||||
val directory = File("${Environment.getExternalStorageDirectory()}${File.separator}Dantotsu${File.separator}Manga")
|
||||
val directory =
|
||||
File("${Environment.getExternalStorageDirectory()}${File.separator}Dantotsu${File.separator}Manga")
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
|
@ -85,7 +99,7 @@ fun saveImage(bitmap: Bitmap, contentResolver: ContentResolver, filename: String
|
|||
}
|
||||
}
|
||||
|
||||
class MangaCache() {
|
||||
class MangaCache {
|
||||
private val maxMemory = (Runtime.getRuntime().maxMemory() / 1024 / 2).toInt()
|
||||
private val cache = LruCache<String, ImageData>(maxMemory)
|
||||
|
||||
|
|
|
@ -15,7 +15,14 @@ data class MangaChapter(
|
|||
val scanlator: String? = null,
|
||||
var progress: String? = ""
|
||||
) : Serializable {
|
||||
constructor(chapter: MangaChapter) : this(chapter.number, chapter.link, chapter.title, chapter.description, chapter.sChapter, chapter.scanlator)
|
||||
constructor(chapter: MangaChapter) : this(
|
||||
chapter.number,
|
||||
chapter.link,
|
||||
chapter.title,
|
||||
chapter.description,
|
||||
chapter.sChapter,
|
||||
chapter.scanlator
|
||||
)
|
||||
|
||||
private val images = mutableListOf<MangaImage>()
|
||||
fun images(): List<MangaImage> = images
|
||||
|
|
|
@ -5,16 +5,15 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import androidx.core.content.ContentProviderCompat.requireContext
|
||||
import androidx.lifecycle.coroutineScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.updateProgress
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ItemChapterListBinding
|
||||
import ani.dantotsu.databinding.ItemEpisodeCompactBinding
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.setAnimation
|
||||
import ani.dantotsu.connections.updateProgress
|
||||
import ani.dantotsu.currContext
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -124,7 +123,7 @@ class MangaChapterAdapter(
|
|||
if (progress != null) {
|
||||
binding.itemChapterTitle.visibility = View.VISIBLE
|
||||
binding.itemChapterTitle.text = "$progress"
|
||||
}else{
|
||||
} else {
|
||||
binding.itemChapterTitle.visibility = View.GONE
|
||||
binding.itemChapterTitle.text = ""
|
||||
}
|
||||
|
@ -154,9 +153,10 @@ class MangaChapterAdapter(
|
|||
// Add chapter number to active coroutines set
|
||||
activeCoroutines.add(chapterNumber)
|
||||
while (activeDownloads.contains(chapterNumber)) {
|
||||
binding.itemDownload.animate().rotationBy(360f).setDuration(1000).setInterpolator(
|
||||
LinearInterpolator()
|
||||
).start()
|
||||
binding.itemDownload.animate().rotationBy(360f).setDuration(1000)
|
||||
.setInterpolator(
|
||||
LinearInterpolator()
|
||||
).start()
|
||||
delay(1000)
|
||||
}
|
||||
// Remove chapter number from active coroutines set
|
||||
|
@ -171,8 +171,16 @@ class MangaChapterAdapter(
|
|||
|
||||
init {
|
||||
val theme = currContext()?.theme
|
||||
theme?.resolveAttribute(com.google.android.material.R.attr.colorError, typedValue1, true)
|
||||
theme?.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue2, true)
|
||||
theme?.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorError,
|
||||
typedValue1,
|
||||
true
|
||||
)
|
||||
theme?.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorPrimary,
|
||||
typedValue2,
|
||||
true
|
||||
)
|
||||
itemView.setOnClickListener {
|
||||
if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size)
|
||||
fragment.onMangaChapterClick(arr[bindingAdapterPosition].number)
|
||||
|
|
|
@ -13,15 +13,12 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.App.Companion.context
|
||||
import ani.dantotsu.media.anime.handleProgress
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.SourceSearchDialogFragment
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.DynamicAnimeParser
|
||||
import ani.dantotsu.media.anime.handleProgress
|
||||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.MangaReadSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
|
@ -30,7 +27,6 @@ import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
|||
import com.google.android.material.chip.Chip
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.lang.IndexOutOfBoundsException
|
||||
|
||||
class MangaReadAdapter(
|
||||
private val media: Media,
|
||||
|
@ -57,12 +53,16 @@ class MangaReadAdapter(
|
|||
|
||||
//Wrong Title
|
||||
binding.animeSourceSearch.setOnClickListener {
|
||||
SourceSearchDialogFragment().show(fragment.requireActivity().supportFragmentManager, null)
|
||||
SourceSearchDialogFragment().show(
|
||||
fragment.requireActivity().supportFragmentManager,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
//Source Selection
|
||||
var source = media.selected!!.sourceIndex.let { if (it >= mangaReadSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex,source)
|
||||
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])
|
||||
mangaReadSources[source].apply {
|
||||
|
@ -70,14 +70,20 @@ class MangaReadAdapter(
|
|||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
}
|
||||
}
|
||||
binding.animeSource.setAdapter(ArrayAdapter(fragment.requireContext(), R.layout.item_dropdown, mangaReadSources.names))
|
||||
binding.animeSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
mangaReadSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSourceTitle.isSelected = true
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
source = i
|
||||
setLanguageList(0,i)
|
||||
setLanguageList(0, i)
|
||||
}
|
||||
subscribeButton(false)
|
||||
//invalidate if it's the last source
|
||||
|
@ -92,7 +98,8 @@ class MangaReadAdapter(
|
|||
fragment.onLangChange(i)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
showUserTextListener =
|
||||
{ MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
setLanguageList(i, source)
|
||||
}
|
||||
subscribeButton(false)
|
||||
|
@ -139,7 +146,8 @@ class MangaReadAdapter(
|
|||
}
|
||||
|
||||
binding.animeScanlatorTop.setOnClickListener {
|
||||
val dialogView = LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
|
||||
val dialogView =
|
||||
LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
|
||||
val checkboxContainer = dialogView.findViewById<LinearLayout>(R.id.checkboxContainer)
|
||||
|
||||
// Dynamically add checkboxes
|
||||
|
@ -149,10 +157,10 @@ class MangaReadAdapter(
|
|||
text = option
|
||||
}
|
||||
//set checked if it's already selected
|
||||
if(media.selected!!.scanlators != null){
|
||||
if (media.selected!!.scanlators != null) {
|
||||
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
|
||||
scanlatorSelectionListener?.onScanlatorsSelected()
|
||||
}else{
|
||||
} else {
|
||||
checkBox.isChecked = true
|
||||
}
|
||||
checkboxContainer.addView(checkBox)
|
||||
|
@ -178,8 +186,8 @@ class MangaReadAdapter(
|
|||
}
|
||||
|
||||
var selected = when (style) {
|
||||
0 -> binding.animeSourceList
|
||||
1 -> binding.animeSourceCompact
|
||||
0 -> binding.animeSourceList
|
||||
1 -> binding.animeSourceCompact
|
||||
else -> binding.animeSourceList
|
||||
}
|
||||
selected.alpha = 1f
|
||||
|
@ -217,14 +225,26 @@ class MangaReadAdapter(
|
|||
for (position in arr.indices) {
|
||||
val last = if (position + 1 == arr.size) names.size else (limit * (position + 1))
|
||||
val chip =
|
||||
ItemChipBinding.inflate(LayoutInflater.from(fragment.context), binding.animeSourceChipGroup, false).root
|
||||
ItemChipBinding.inflate(
|
||||
LayoutInflater.from(fragment.context),
|
||||
binding.animeSourceChipGroup,
|
||||
false
|
||||
).root
|
||||
chip.isCheckable = true
|
||||
fun selected() {
|
||||
chip.isChecked = true
|
||||
binding.animeWatchChipScroll.smoothScrollTo((chip.left - screenWidth / 2) + (chip.width / 2), 0)
|
||||
binding.animeWatchChipScroll.smoothScrollTo(
|
||||
(chip.left - screenWidth / 2) + (chip.width / 2),
|
||||
0
|
||||
)
|
||||
}
|
||||
chip.text = "${names[limit * (position)]} - ${names[last - 1]}"
|
||||
chip.setTextColor(ContextCompat.getColorStateList(fragment.requireContext(), R.color.chip_text_color))
|
||||
chip.setTextColor(
|
||||
ContextCompat.getColorStateList(
|
||||
fragment.requireContext(),
|
||||
R.color.chip_text_color
|
||||
)
|
||||
)
|
||||
|
||||
chip.setOnClickListener {
|
||||
selected()
|
||||
|
@ -237,7 +257,14 @@ class MangaReadAdapter(
|
|||
}
|
||||
}
|
||||
if (select != null)
|
||||
binding.animeWatchChipScroll.apply { post { scrollTo((select.left - screenWidth / 2) + (select.width / 2), 0) } }
|
||||
binding.animeWatchChipScroll.apply {
|
||||
post {
|
||||
scrollTo(
|
||||
(select.left - screenWidth / 2) + (select.width / 2),
|
||||
0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,7 +286,9 @@ class MangaReadAdapter(
|
|||
val chapter = media.manga.chapters!![chapterKey]!!
|
||||
chapter.scanlator !in hiddenScanlators
|
||||
}
|
||||
val formattedChapters = filteredChapters.map { MangaNameAdapter.findChapterNumber(it)?.toInt()?.toString() }
|
||||
val formattedChapters = filteredChapters.map {
|
||||
MangaNameAdapter.findChapterNumber(it)?.toInt()?.toString()
|
||||
}
|
||||
if (formattedChapters.contains(continueEp)) {
|
||||
continueEp = chapters[formattedChapters.indexOf(continueEp)]
|
||||
binding.animeSourceContinue.visibility = View.VISIBLE
|
||||
|
@ -317,10 +346,17 @@ class MangaReadAdapter(
|
|||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
}catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources.firstOrNull()?.lang ?: "Unknown")
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(
|
||||
parser.extension.sources.firstOrNull()?.lang ?: "Unknown"
|
||||
)
|
||||
}
|
||||
binding?.animeSourceLanguage?.setAdapter(ArrayAdapter(fragment.requireContext(), R.layout.item_dropdown, parser.extension.sources.map { it.lang }))
|
||||
binding?.animeSourceLanguage?.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
parser.extension.sources.map { it.lang })
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +364,8 @@ class MangaReadAdapter(
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
|
||||
interface ScanlatorSelectionListener {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ani.dantotsu.media.manga
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.BroadcastReceiver
|
||||
|
@ -16,6 +17,7 @@ import android.view.ViewGroup
|
|||
import android.widget.FrameLayout
|
||||
import android.widget.Toast
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.math.MathUtils.clamp
|
||||
import androidx.core.view.updatePadding
|
||||
|
@ -31,10 +33,10 @@ import ani.dantotsu.download.Download
|
|||
import ani.dantotsu.download.DownloadsManager
|
||||
import ani.dantotsu.download.manga.MangaDownloaderService
|
||||
import ani.dantotsu.download.manga.MangaServiceDataSingleton
|
||||
import ani.dantotsu.media.manga.mangareader.ChapterLoaderDialog
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.manga.mangareader.ChapterLoaderDialog
|
||||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaParser
|
||||
|
@ -59,10 +61,8 @@ import uy.kohesive.injekt.api.get
|
|||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
import android.Manifest
|
||||
import androidx.core.app.ActivityCompat
|
||||
|
||||
open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||
open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
||||
private var _binding: FragmentAnimeWatchBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
@ -85,7 +85,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
var continueEp: Boolean = false
|
||||
var loaded = false
|
||||
|
||||
val uiSettings = loadData("ui_settings", toast = false) ?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
|
||||
val uiSettings = loadData("ui_settings", toast = false)
|
||||
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
@ -105,7 +106,12 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
addAction(ACTION_DOWNLOAD_PROGRESS)
|
||||
}
|
||||
|
||||
ContextCompat.registerReceiver(requireContext(), downloadStatusReceiver, intentFilter, ContextCompat.RECEIVER_EXPORTED)
|
||||
ContextCompat.registerReceiver(
|
||||
requireContext(),
|
||||
downloadStatusReceiver,
|
||||
intentFilter,
|
||||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
screenWidth = resources.displayMetrics.widthPixels.dp
|
||||
|
@ -120,10 +126,10 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
val style = chapterAdapter.getItemViewType(position)
|
||||
|
||||
return when (position) {
|
||||
0 -> maxGridSize
|
||||
0 -> maxGridSize
|
||||
else -> when (style) {
|
||||
0 -> maxGridSize
|
||||
1 -> 1
|
||||
0 -> maxGridSize
|
||||
1 -> 1
|
||||
else -> maxGridSize
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +152,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
if (media.format == "MANGA" || media.format == "ONE SHOT") {
|
||||
media.selected = model.loadSelected(media)
|
||||
|
||||
subscribed = SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id)
|
||||
subscribed =
|
||||
SubscriptionHelper.getSubscriptions(requireContext()).containsKey(media.id)
|
||||
|
||||
style = media.selected!!.recyclerStyle
|
||||
reverse = media.selected!!.recyclerReversed
|
||||
|
@ -156,13 +163,15 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
|
||||
headerAdapter = MangaReadAdapter(it, this, model.mangaReadSources!!)
|
||||
headerAdapter.scanlatorSelectionListener = this
|
||||
chapterAdapter = MangaChapterAdapter(style ?: uiSettings.mangaDefaultView, media, this)
|
||||
chapterAdapter =
|
||||
MangaChapterAdapter(style ?: uiSettings.mangaDefaultView, media, this)
|
||||
|
||||
for (download in downloadManager.mangaDownloads){
|
||||
for (download in downloadManager.mangaDownloads) {
|
||||
chapterAdapter.stopDownload(download.chapter)
|
||||
}
|
||||
|
||||
binding.animeSourceRecycler.adapter = ConcatAdapter(headerAdapter, chapterAdapter)
|
||||
binding.animeSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, chapterAdapter)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
model.loadMangaChapters(media, media.selected!!.sourceIndex)
|
||||
|
@ -173,7 +182,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
} else {
|
||||
binding.animeNotSupported.visibility = View.VISIBLE
|
||||
binding.animeNotSupported.text = getString(R.string.not_supported, media.format ?: "")
|
||||
binding.animeNotSupported.text =
|
||||
getString(R.string.not_supported, media.format ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +217,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
val limit = when {
|
||||
(divisions < 25) -> 25
|
||||
(divisions < 50) -> 50
|
||||
else -> 100
|
||||
else -> 100
|
||||
}
|
||||
headerAdapter.clearChips()
|
||||
if (total > limit) {
|
||||
|
@ -302,7 +312,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
)
|
||||
}
|
||||
|
||||
fun openSettings(pkg: MangaExtension.Installed){
|
||||
fun openSettings(pkg: MangaExtension.Installed) {
|
||||
val changeUIVisibility: (Boolean) -> Unit = { show ->
|
||||
val activity = requireActivity() as MediaDetailsActivity
|
||||
val visibility = if (show) View.VISIBLE else View.GONE
|
||||
|
@ -310,9 +320,9 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
activity.findViewById<ViewPager2>(R.id.mediaViewPager).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaCover).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaClose).visibility = visibility
|
||||
try{
|
||||
try {
|
||||
activity.findViewById<CustomBottomNavBar>(R.id.mediaTab).visibility = visibility
|
||||
}catch (e: ClassCastException){
|
||||
} catch (e: ClassCastException) {
|
||||
activity.findViewById<NavigationRailView>(R.id.mediaTab).visibility = visibility
|
||||
}
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
|
||||
|
@ -335,7 +345,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
|
||||
// Move the fragment transaction here
|
||||
val fragment =
|
||||
MangaSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
|
@ -353,7 +363,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
.show()
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id) {
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
|
@ -376,7 +386,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
media.manga?.chapters?.get(i)?.let {
|
||||
media.manga?.selectedChapter = i
|
||||
model.saveSelected(media.id, media.selected!!, requireActivity())
|
||||
ChapterLoaderDialog.newInstance(it, true).show(requireActivity().supportFragmentManager, "dialog")
|
||||
ChapterLoaderDialog.newInstance(it, true)
|
||||
.show(requireActivity().supportFragmentManager, "dialog")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,7 +404,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
|
||||
model.continueMedia = false
|
||||
media.manga?.chapters?.get(i)?.let { chapter ->
|
||||
val parser = model.mangaReadSources?.get(media.selected!!.sourceIndex) as? DynamicMangaParser
|
||||
val parser =
|
||||
model.mangaReadSources?.get(media.selected!!.sourceIndex) as? DynamicMangaParser
|
||||
parser?.let {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val images = parser.imageList("", chapter.sChapter)
|
||||
|
@ -439,10 +451,17 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
}
|
||||
|
||||
|
||||
fun onMangaChapterRemoveDownloadClick(i: String){
|
||||
downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA))
|
||||
fun onMangaChapterRemoveDownloadClick(i: String) {
|
||||
downloadManager.removeDownload(
|
||||
Download(
|
||||
media.nameMAL ?: media.nameRomaji,
|
||||
i,
|
||||
Download.Type.MANGA
|
||||
)
|
||||
)
|
||||
chapterAdapter.deleteDownload(i)
|
||||
}
|
||||
|
||||
fun onMangaChapterStopDownloadClick(i: String) {
|
||||
val cancelIntent = Intent().apply {
|
||||
action = MangaDownloaderService.ACTION_CANCEL_DOWNLOAD
|
||||
|
@ -451,12 +470,19 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
requireContext().sendBroadcast(cancelIntent)
|
||||
|
||||
// Remove the download from the manager and update the UI
|
||||
downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA))
|
||||
downloadManager.removeDownload(
|
||||
Download(
|
||||
media.nameMAL ?: media.nameRomaji,
|
||||
i,
|
||||
Download.Type.MANGA
|
||||
)
|
||||
)
|
||||
chapterAdapter.purgeDownload(i)
|
||||
}
|
||||
|
||||
private val downloadStatusReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if(!this@MangaReadFragment::chapterAdapter.isInitialized) return
|
||||
if (!this@MangaReadFragment::chapterAdapter.isInitialized) return
|
||||
when (intent.action) {
|
||||
ACTION_DOWNLOAD_STARTED -> {
|
||||
val chapterNumber = intent.getStringExtra(EXTRA_CHAPTER_NUMBER)
|
||||
|
@ -492,8 +518,10 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest chapter for subscription
|
||||
selected.latest = media.manga?.chapters?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest = media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
||||
selected.latest =
|
||||
media.manga?.chapters?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
||||
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
headerAdapter.handleChapters()
|
||||
|
@ -502,7 +530,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
|
|||
if (media.manga!!.chapters != null) {
|
||||
val end = if (end != null && end!! < media.manga!!.chapters!!.size) end else null
|
||||
arr.addAll(
|
||||
media.manga!!.chapters!!.values.toList().slice(start..(end ?: (media.manga!!.chapters!!.size - 1)))
|
||||
media.manga!!.chapters!!.values.toList()
|
||||
.slice(start..(end ?: (media.manga!!.chapters!!.size - 1)))
|
||||
)
|
||||
if (reverse)
|
||||
arr = (arr.reversed() as? ArrayList<MangaChapter>) ?: arr
|
||||
|
|
|
@ -14,8 +14,8 @@ import androidx.core.view.updateLayoutParams
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.settings.CurrentReaderSettings
|
||||
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
||||
import com.bumptech.glide.Glide
|
||||
|
@ -23,12 +23,9 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
|
||||
|
@ -118,7 +115,10 @@ abstract class BaseImageAdapter(
|
|||
abstract suspend fun loadImage(position: Int, parent: View): Boolean
|
||||
|
||||
companion object {
|
||||
suspend fun Context.loadBitmap_old(link: FileUrl, transforms: List<BitmapTransformation>): Bitmap? { //still used in some places
|
||||
suspend fun Context.loadBitmap_old(
|
||||
link: FileUrl,
|
||||
transforms: List<BitmapTransformation>
|
||||
): Bitmap? { //still used in some places
|
||||
return tryWithSuspend {
|
||||
withContext(Dispatchers.IO) {
|
||||
Glide.with(this@loadBitmap_old)
|
||||
|
@ -135,8 +135,7 @@ abstract class BaseImageAdapter(
|
|||
.let {
|
||||
if (transforms.isNotEmpty()) {
|
||||
it.transform(*transforms.toTypedArray())
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +145,10 @@ abstract class BaseImageAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun Context.loadBitmap(link: FileUrl, transforms: List<BitmapTransformation>): Bitmap? {
|
||||
suspend fun Context.loadBitmap(
|
||||
link: FileUrl,
|
||||
transforms: List<BitmapTransformation>
|
||||
): Bitmap? {
|
||||
return tryWithSuspend {
|
||||
val mangaCache = uy.kohesive.injekt.Injekt.get<MangaCache>()
|
||||
withContext(Dispatchers.IO) {
|
||||
|
@ -161,7 +163,11 @@ abstract class BaseImageAdapter(
|
|||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
} else {
|
||||
mangaCache.get(link.url)?.let { imageData ->
|
||||
val bitmap = imageData.fetchAndProcessImage(imageData.page, imageData.source, context = this@loadBitmap)
|
||||
val bitmap = imageData.fetchAndProcessImage(
|
||||
imageData.page,
|
||||
imageData.source,
|
||||
context = this@loadBitmap
|
||||
)
|
||||
it.load(bitmap)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
|
|
|
@ -14,9 +14,9 @@ import ani.dantotsu.BottomSheetDialogFragment
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.currActivity
|
||||
import ani.dantotsu.databinding.BottomSheetSelectorBinding
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaSingleton
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.tryWith
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -29,8 +29,8 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
|
|||
|
||||
val model: MediaDetailsViewModel by activityViewModels()
|
||||
|
||||
private val launch : Boolean by lazy { arguments?.getBoolean("launch", false) ?: false }
|
||||
private val chp : MangaChapter by lazy { arguments?.getSerialized("next")!! }
|
||||
private val launch: Boolean by lazy { arguments?.getBoolean("launch", false) ?: false }
|
||||
private val chp: MangaChapter by lazy { arguments?.getSerialized("next")!! }
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
var loaded = false
|
||||
|
@ -47,13 +47,21 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
|
|||
loaded = true
|
||||
binding.selectorAutoText.text = chp.title
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
if(model.loadMangaChapterImages(chp, m.selected!!, m.nameMAL?:m.nameRomaji)) {
|
||||
if (model.loadMangaChapterImages(
|
||||
chp,
|
||||
m.selected!!,
|
||||
m.nameMAL ?: m.nameRomaji
|
||||
)
|
||||
) {
|
||||
val activity = currActivity()
|
||||
activity?.runOnUiThread {
|
||||
tryWith { dismiss() }
|
||||
if(launch) {
|
||||
if (launch) {
|
||||
MediaSingleton.media = m
|
||||
val intent = Intent(activity, MangaReaderActivity::class.java)//.apply { putExtra("media", m) }
|
||||
val intent = Intent(
|
||||
activity,
|
||||
MangaReaderActivity::class.java
|
||||
)//.apply { putExtra("media", m) }
|
||||
activity.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +71,11 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetSelectorBinding.inflate(inflater, container, false)
|
||||
val window = dialog?.window
|
||||
window?.statusBarColor = Color.TRANSPARENT
|
||||
|
|
|
@ -30,15 +30,15 @@ open class ImageAdapter(
|
|||
|
||||
inner class ImageViewHolder(binding: ItemImageBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
open suspend fun loadBitmap(position: Int, parent: View) : Bitmap? {
|
||||
open suspend fun loadBitmap(position: Int, parent: View): Bitmap? {
|
||||
val link = images.getOrNull(position)?.url ?: return null
|
||||
if (link.url.isEmpty()) return null
|
||||
|
||||
val transforms = mutableListOf<BitmapTransformation>()
|
||||
val parserTransformation = activity.getTransformation(images[position])
|
||||
|
||||
if(parserTransformation!=null) transforms.add(parserTransformation)
|
||||
if(settings.cropBorders) {
|
||||
if (parserTransformation != null) transforms.add(parserTransformation)
|
||||
if (settings.cropBorders) {
|
||||
transforms.add(RemoveBordersTransformation(true, settings.cropBorderThreshold))
|
||||
transforms.add(RemoveBordersTransformation(false, settings.cropBorderThreshold))
|
||||
}
|
||||
|
@ -47,7 +47,8 @@ open class ImageAdapter(
|
|||
}
|
||||
|
||||
override suspend fun loadImage(position: Int, parent: View): Boolean {
|
||||
val imageView = parent.findViewById<SubsamplingScaleImageView>(R.id.imgProgImageNoGestures) ?: return false
|
||||
val imageView = parent.findViewById<SubsamplingScaleImageView>(R.id.imgProgImageNoGestures)
|
||||
?: return false
|
||||
val progress = parent.findViewById<View>(R.id.imgProgProgress) ?: return false
|
||||
imageView.recycle()
|
||||
imageView.visibility = View.GONE
|
||||
|
@ -60,10 +61,12 @@ open class ImageAdapter(
|
|||
if (settings.layout != PAGED)
|
||||
parent.updateLayoutParams {
|
||||
if (settings.direction != LEFT_TO_RIGHT && settings.direction != RIGHT_TO_LEFT) {
|
||||
sHeight = if (settings.wrapImages) bitmap.height else (sWidth * bitmap.height * 1f / bitmap.width).toInt()
|
||||
sHeight =
|
||||
if (settings.wrapImages) bitmap.height else (sWidth * bitmap.height * 1f / bitmap.width).toInt()
|
||||
height = sHeight
|
||||
} else {
|
||||
sWidth = if (settings.wrapImages) bitmap.width else (sHeight * bitmap.width * 1f / bitmap.height).toInt()
|
||||
sWidth =
|
||||
if (settings.wrapImages) bitmap.width else (sHeight * bitmap.width * 1f / bitmap.height).toInt()
|
||||
width = sWidth
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +76,8 @@ open class ImageAdapter(
|
|||
|
||||
val parentArea = sWidth * sHeight * 1f
|
||||
val bitmapArea = bitmap.width * bitmap.height * 1f
|
||||
val scale = if (parentArea < bitmapArea) (bitmapArea / parentArea) else (parentArea / bitmapArea)
|
||||
val scale =
|
||||
if (parentArea < bitmapArea) (bitmapArea / parentArea) else (parentArea / bitmapArea)
|
||||
|
||||
imageView.maxScale = scale * 1.1f
|
||||
imageView.minScale = scale
|
||||
|
|
|
@ -34,12 +34,11 @@ import ani.dantotsu.databinding.ActivityMangaReaderBinding
|
|||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.media.MediaSingleton
|
||||
import ani.dantotsu.media.anime.ExoplayerView
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import ani.dantotsu.media.manga.MangaChapter
|
||||
import ani.dantotsu.media.manga.MangaNameAdapter
|
||||
import ani.dantotsu.others.ImageViewDialog
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaImage
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
|
@ -50,7 +49,6 @@ import ani.dantotsu.settings.CurrentReaderSettings.Layouts.*
|
|||
import ani.dantotsu.settings.ReaderSettings
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
|
@ -58,8 +56,6 @@ import com.google.firebase.crashlytics.ktx.crashlytics
|
|||
import com.google.firebase.ktx.Firebase
|
||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
@ -262,16 +258,16 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
if (showProgressDialog && Anilist.userid != null && if (media.isAdult) settings.updateForH else true)
|
||||
AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.title_update_progress)).apply {
|
||||
setMultiChoiceItems(
|
||||
arrayOf(getString(R.string.dont_ask_again, media.userPreferredName)),
|
||||
booleanArrayOf(false)
|
||||
) { _, _, isChecked ->
|
||||
if (isChecked) progressDialog = null
|
||||
saveData("${media.id}_progressDialog", isChecked)
|
||||
showProgressDialog = isChecked
|
||||
setMultiChoiceItems(
|
||||
arrayOf(getString(R.string.dont_ask_again, media.userPreferredName)),
|
||||
booleanArrayOf(false)
|
||||
) { _, _, isChecked ->
|
||||
if (isChecked) progressDialog = null
|
||||
saveData("${media.id}_progressDialog", isChecked)
|
||||
showProgressDialog = isChecked
|
||||
}
|
||||
setOnCancelListener { hideBars() }
|
||||
}
|
||||
setOnCancelListener { hideBars() }
|
||||
}
|
||||
else null
|
||||
|
||||
//Chapter Change
|
||||
|
|
|
@ -10,14 +10,15 @@ import kotlin.math.max
|
|||
|
||||
class PreloadLinearLayoutManager(context: Context, orientation: Int, reverseLayout: Boolean) :
|
||||
LinearLayoutManager(context, orientation, reverseLayout) {
|
||||
private val mOrientationHelper: OrientationHelper = OrientationHelper.createOrientationHelper(this, orientation)
|
||||
private val mOrientationHelper: OrientationHelper =
|
||||
OrientationHelper.createOrientationHelper(this, orientation)
|
||||
|
||||
/**
|
||||
* As [LinearLayoutManager.collectAdjacentPrefetchPositions] will prefetch one view for us,
|
||||
* we only need to prefetch additional ones.
|
||||
*/
|
||||
var preloadItemCount = 1
|
||||
set(count){
|
||||
set(count) {
|
||||
require(count >= 1) { "preloadItemCount must not be smaller than 1!" }
|
||||
field = count - 1
|
||||
}
|
||||
|
@ -37,7 +38,8 @@ class PreloadLinearLayoutManager(context: Context, orientation: Int, reverseLayo
|
|||
val currentPosition: Int = getPosition(child ?: return) + layoutDirection
|
||||
|
||||
if (layoutDirection == 1) {
|
||||
val scrollingOffset = (mOrientationHelper.getDecoratedEnd(child) - mOrientationHelper.endAfterPadding)
|
||||
val scrollingOffset =
|
||||
(mOrientationHelper.getDecoratedEnd(child) - mOrientationHelper.endAfterPadding)
|
||||
((currentPosition + 1) until (currentPosition + preloadItemCount + 1)).forEach {
|
||||
if (it >= 0 && it < state.itemCount) {
|
||||
layoutPrefetchRegistry.addPosition(it, max(0, scrollingOffset))
|
||||
|
|
|
@ -14,7 +14,11 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
private var _binding: BottomSheetCurrentReaderSettingsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetCurrentReaderSettingsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -24,11 +28,14 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
val activity = requireActivity() as MangaReaderActivity
|
||||
val settings = activity.settings.default
|
||||
|
||||
binding.readerDirectionText.text = resources.getStringArray(R.array.manga_directions)[settings.direction.ordinal]
|
||||
binding.readerDirectionText.text =
|
||||
resources.getStringArray(R.array.manga_directions)[settings.direction.ordinal]
|
||||
binding.readerDirection.rotation = 90f * (settings.direction.ordinal)
|
||||
binding.readerDirection.setOnClickListener {
|
||||
settings.direction = Directions[settings.direction.ordinal + 1] ?: Directions.TOP_TO_BOTTOM
|
||||
binding.readerDirectionText.text = resources.getStringArray(R.array.manga_directions)[settings.direction.ordinal]
|
||||
settings.direction =
|
||||
Directions[settings.direction.ordinal + 1] ?: Directions.TOP_TO_BOTTOM
|
||||
binding.readerDirectionText.text =
|
||||
resources.getStringArray(R.array.manga_directions)[settings.direction.ordinal]
|
||||
binding.readerDirection.rotation = 90f * (settings.direction.ordinal)
|
||||
activity.applySettings()
|
||||
}
|
||||
|
@ -39,36 +46,39 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
binding.readerContinuous
|
||||
)
|
||||
|
||||
binding.readerPadding.isEnabled = settings.layout.ordinal!=0
|
||||
fun paddingAvailable(enable:Boolean){
|
||||
binding.readerPadding.isEnabled = settings.layout.ordinal != 0
|
||||
fun paddingAvailable(enable: Boolean) {
|
||||
binding.readerPadding.isEnabled = enable
|
||||
}
|
||||
|
||||
binding.readerPadding.isChecked = settings.padding
|
||||
binding.readerPadding.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerPadding.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.padding = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.readerCropBorders.isChecked = settings.cropBorders
|
||||
binding.readerCropBorders.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerCropBorders.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.cropBorders = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.readerLayoutText.text = resources.getStringArray(R.array.manga_layouts)[settings.layout.ordinal]
|
||||
binding.readerLayoutText.text =
|
||||
resources.getStringArray(R.array.manga_layouts)[settings.layout.ordinal]
|
||||
var selected = list[settings.layout.ordinal]
|
||||
selected.alpha = 1f
|
||||
|
||||
list.forEachIndexed { index , imageButton ->
|
||||
list.forEachIndexed { index, imageButton ->
|
||||
imageButton.setOnClickListener {
|
||||
selected.alpha = 0.33f
|
||||
selected = imageButton
|
||||
selected.alpha = 1f
|
||||
settings.layout = CurrentReaderSettings.Layouts[index]?:CurrentReaderSettings.Layouts.CONTINUOUS
|
||||
binding.readerLayoutText.text = resources.getStringArray(R.array.manga_layouts)[settings.layout.ordinal]
|
||||
settings.layout =
|
||||
CurrentReaderSettings.Layouts[index] ?: CurrentReaderSettings.Layouts.CONTINUOUS
|
||||
binding.readerLayoutText.text =
|
||||
resources.getStringArray(R.array.manga_layouts)[settings.layout.ordinal]
|
||||
activity.applySettings()
|
||||
paddingAvailable(settings.layout.ordinal!=0)
|
||||
paddingAvailable(settings.layout.ordinal != 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +97,8 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
selectedDual.alpha = 0.33f
|
||||
selectedDual = imageButton
|
||||
selectedDual.alpha = 1f
|
||||
settings.dualPageMode = CurrentReaderSettings.DualPageModes[index] ?: CurrentReaderSettings.DualPageModes.Automatic
|
||||
settings.dualPageMode = CurrentReaderSettings.DualPageModes[index]
|
||||
?: CurrentReaderSettings.DualPageModes.Automatic
|
||||
binding.readerDualPageText.text = settings.dualPageMode.toString()
|
||||
activity.applySettings()
|
||||
}
|
||||
|
@ -111,37 +122,37 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
binding.readerKeepScreenOn.isChecked = settings.keepScreenOn
|
||||
binding.readerKeepScreenOn.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerKeepScreenOn.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.keepScreenOn = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.readerHidePageNumbers.isChecked = settings.hidePageNumbers
|
||||
binding.readerHidePageNumbers.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerHidePageNumbers.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.hidePageNumbers = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.readerOverscroll.isChecked = settings.overScrollMode
|
||||
binding.readerOverscroll.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerOverscroll.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.overScrollMode = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.readerVolumeButton.isChecked = settings.volumeButtons
|
||||
binding.readerVolumeButton.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerVolumeButton.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.volumeButtons = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.readerWrapImage.isChecked = settings.wrapImages
|
||||
binding.readerWrapImage.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerWrapImage.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.wrapImages = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.readerLongClickImage.isChecked = settings.longClickImage
|
||||
binding.readerLongClickImage.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.readerLongClickImage.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.longClickImage = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
@ -152,7 +163,7 @@ class ReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
super.onDestroy()
|
||||
}
|
||||
|
||||
companion object{
|
||||
companion object {
|
||||
fun newInstance() = ReaderSettingsDialogFragment()
|
||||
}
|
||||
}
|
|
@ -6,7 +6,8 @@ import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
|||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import java.security.MessageDigest
|
||||
|
||||
class RemoveBordersTransformation(private val white:Boolean, private val threshHold:Int) : BitmapTransformation() {
|
||||
class RemoveBordersTransformation(private val white: Boolean, private val threshHold: Int) :
|
||||
BitmapTransformation() {
|
||||
|
||||
override fun transform(
|
||||
pool: BitmapPool,
|
||||
|
@ -95,6 +96,6 @@ class RemoveBordersTransformation(private val white:Boolean, private val threshH
|
|||
|
||||
private fun isPixelNotWhite(pixel: Int): Boolean {
|
||||
val brightness = Color.red(pixel) + Color.green(pixel) + Color.blue(pixel)
|
||||
return if(white) brightness < (255-threshHold) else brightness > threshHold
|
||||
return if (white) brightness < (255 - threshHold) else brightness > threshHold
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class Swipy @JvmOverloads constructor(
|
|||
context: Context, attrs: AttributeSet? = null
|
||||
) : FrameLayout(context, attrs) {
|
||||
|
||||
var dragDivider : Int = 5
|
||||
var dragDivider: Int = 5
|
||||
var vertical = true
|
||||
|
||||
//public, in case a different sub child needs to be considered
|
||||
|
@ -100,7 +100,7 @@ class Swipy @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
when (action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
activePointerId = ev.getPointerId(0)
|
||||
isBeingDragged = false
|
||||
pointerIndex = ev.findPointerIndex(activePointerId)
|
||||
|
@ -109,7 +109,8 @@ class Swipy @JvmOverloads constructor(
|
|||
}
|
||||
initialDown = if (vertical) ev.getY(pointerIndex) else ev.getX(pointerIndex)
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
if (activePointerId == INVALID_POINTER) {
|
||||
//("Got ACTION_MOVE event but don't have an active pointer id.")
|
||||
return false
|
||||
|
@ -121,7 +122,8 @@ class Swipy @JvmOverloads constructor(
|
|||
val pos = if (vertical) ev.getY(pointerIndex) else ev.getX(pointerIndex)
|
||||
startDragging(pos)
|
||||
}
|
||||
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
||||
|
||||
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
isBeingDragged = false
|
||||
activePointerId = INVALID_POINTER
|
||||
|
@ -138,11 +140,12 @@ class Swipy @JvmOverloads constructor(
|
|||
return false
|
||||
}
|
||||
when (action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
activePointerId = ev.getPointerId(0)
|
||||
isBeingDragged = false
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
pointerIndex = ev.findPointerIndex(activePointerId)
|
||||
if (pointerIndex < 0) {
|
||||
//("Got ACTION_MOVE event but have an invalid active pointer id.")
|
||||
|
@ -160,16 +163,16 @@ class Swipy @JvmOverloads constructor(
|
|||
|
||||
if (overscroll > 0) {
|
||||
parent.requestDisallowInterceptTouchEvent(true)
|
||||
if (vertical){
|
||||
val totalDragDistance = Resources.getSystem().displayMetrics.heightPixels / dragDivider
|
||||
if (vertical) {
|
||||
val totalDragDistance =
|
||||
Resources.getSystem().displayMetrics.heightPixels / dragDivider
|
||||
if (verticalPos == VerticalPosition.Top)
|
||||
topBeingSwiped.invoke(overscroll / totalDragDistance)
|
||||
else
|
||||
bottomBeingSwiped.invoke(overscroll / totalDragDistance)
|
||||
}
|
||||
|
||||
else {
|
||||
val totalDragDistance = Resources.getSystem().displayMetrics.widthPixels / dragDivider
|
||||
} else {
|
||||
val totalDragDistance =
|
||||
Resources.getSystem().displayMetrics.widthPixels / dragDivider
|
||||
if (horizontalPos == HorizontalPosition.Left)
|
||||
leftBeingSwiped.invoke(overscroll / totalDragDistance)
|
||||
else
|
||||
|
@ -180,6 +183,7 @@ class Swipy @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_POINTER_DOWN -> {
|
||||
pointerIndex = ev.actionIndex
|
||||
if (pointerIndex < 0) {
|
||||
|
@ -188,8 +192,9 @@ class Swipy @JvmOverloads constructor(
|
|||
}
|
||||
activePointerId = ev.getPointerId(pointerIndex)
|
||||
}
|
||||
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
||||
MotionEvent.ACTION_UP -> {
|
||||
|
||||
MotionEvent.ACTION_POINTER_UP -> onSecondaryPointerUp(ev)
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (vertical) {
|
||||
topBeingSwiped.invoke(0f)
|
||||
bottomBeingSwiped.invoke(0f)
|
||||
|
@ -216,7 +221,8 @@ class Swipy @JvmOverloads constructor(
|
|||
activePointerId = INVALID_POINTER
|
||||
return false
|
||||
}
|
||||
MotionEvent.ACTION_CANCEL -> return false
|
||||
|
||||
MotionEvent.ACTION_CANCEL -> return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -235,21 +241,20 @@ class Swipy @JvmOverloads constructor(
|
|||
|
||||
private fun finishSpinner(overscrollDistance: Float) {
|
||||
|
||||
if (vertical) {
|
||||
val totalDragDistance = Resources.getSystem().displayMetrics.heightPixels / dragDivider
|
||||
if (overscrollDistance > totalDragDistance)
|
||||
if (verticalPos == VerticalPosition.Top)
|
||||
onTopSwiped.invoke()
|
||||
else
|
||||
onBottomSwiped.invoke()
|
||||
}
|
||||
else {
|
||||
val totalDragDistance = Resources.getSystem().displayMetrics.widthPixels / dragDivider
|
||||
if (overscrollDistance > totalDragDistance)
|
||||
if (vertical) {
|
||||
val totalDragDistance = Resources.getSystem().displayMetrics.heightPixels / dragDivider
|
||||
if (overscrollDistance > totalDragDistance)
|
||||
if (verticalPos == VerticalPosition.Top)
|
||||
onTopSwiped.invoke()
|
||||
else
|
||||
onBottomSwiped.invoke()
|
||||
} else {
|
||||
val totalDragDistance = Resources.getSystem().displayMetrics.widthPixels / dragDivider
|
||||
if (overscrollDistance > totalDragDistance)
|
||||
if (horizontalPos == HorizontalPosition.Left)
|
||||
onLeftSwiped.invoke()
|
||||
else
|
||||
onRightSwiped.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,8 +13,6 @@ import ani.dantotsu.loadImage
|
|||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.others.getSerialized
|
||||
import ani.dantotsu.parsers.ShowResponse
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -25,13 +23,14 @@ class BookDialog : BottomSheetDialogFragment() {
|
|||
|
||||
private val viewModel by activityViewModels<MediaDetailsViewModel>()
|
||||
|
||||
private lateinit var novelName:String
|
||||
private lateinit var novelName: String
|
||||
private lateinit var novel: ShowResponse
|
||||
private var source:Int = 0
|
||||
private var source: Int = 0
|
||||
|
||||
interface Callback {
|
||||
fun onDownloadTriggered(link: String)
|
||||
}
|
||||
|
||||
private var callback: Callback? = null
|
||||
fun setCallback(callback: Callback) {
|
||||
this.callback = callback
|
||||
|
@ -46,7 +45,11 @@ class BookDialog : BottomSheetDialogFragment() {
|
|||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetBookBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -55,7 +58,7 @@ class BookDialog : BottomSheetDialogFragment() {
|
|||
binding.bookRecyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
|
||||
viewModel.book.observe(viewLifecycleOwner) {
|
||||
if(it!=null){
|
||||
if (it != null) {
|
||||
binding.itemBookTitle.text = it.name
|
||||
binding.itemBookDesc.text = it.description
|
||||
binding.itemBookImage.loadImage(it.img)
|
||||
|
@ -73,7 +76,7 @@ class BookDialog : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(novelName:String, novel:ShowResponse, source: Int) : BookDialog{
|
||||
fun newInstance(novelName: String, novel: ShowResponse, source: Int): BookDialog {
|
||||
val bundle = Bundle().apply {
|
||||
putString("novelName", novelName)
|
||||
putInt("source", source)
|
||||
|
|
|
@ -22,12 +22,14 @@ class NovelReadAdapter(
|
|||
var progress: View? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NovelReadAdapter.ViewHolder {
|
||||
val binding = ItemNovelHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val binding =
|
||||
ItemNovelHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
progress = binding.progress.root
|
||||
return ViewHolder(binding)
|
||||
}
|
||||
|
||||
private val imm = fragment.requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
private val imm = fragment.requireContext()
|
||||
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val binding = holder.binding
|
||||
|
@ -35,7 +37,8 @@ class NovelReadAdapter(
|
|||
|
||||
fun search(): Boolean {
|
||||
val query = binding.searchBarText.text.toString()
|
||||
val source = media.selected!!.sourceIndex.let { if (it >= novelReadSources.names.size) 0 else it }
|
||||
val source =
|
||||
media.selected!!.sourceIndex.let { if (it >= novelReadSources.names.size) 0 else it }
|
||||
fragment.source = source
|
||||
|
||||
binding.searchBarText.clearFocus()
|
||||
|
@ -44,11 +47,18 @@ class NovelReadAdapter(
|
|||
return true
|
||||
}
|
||||
|
||||
val source = media.selected!!.sourceIndex.let { if (it >= novelReadSources.names.size) 0 else it }
|
||||
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.animeSource.setAdapter(ArrayAdapter(fragment.requireContext(), R.layout.item_dropdown, novelReadSources.names))
|
||||
binding.animeSource.setAdapter(
|
||||
ArrayAdapter(
|
||||
fragment.requireContext(),
|
||||
R.layout.item_dropdown,
|
||||
novelReadSources.names
|
||||
)
|
||||
)
|
||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||
fragment.onSourceChange(i)
|
||||
search()
|
||||
|
@ -58,7 +68,7 @@ class NovelReadAdapter(
|
|||
binding.searchBarText.setOnEditorActionListener { _, actionId, _ ->
|
||||
return@setOnEditorActionListener when (actionId) {
|
||||
IME_ACTION_SEARCH -> search()
|
||||
else -> false
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
binding.searchBar.setEndIconOnClickListener { search() }
|
||||
|
@ -66,5 +76,6 @@ class NovelReadAdapter(
|
|||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemNovelHeaderBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
inner class ViewHolder(val binding: ItemNovelHeaderBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
|
@ -61,7 +61,8 @@ class NovelReadFragment : Fragment(),
|
|||
private var continueEp: Boolean = false
|
||||
var loaded = false
|
||||
|
||||
val uiSettings = loadData("ui_settings", toast = false) ?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
|
||||
val uiSettings = loadData("ui_settings", toast = false)
|
||||
?: UserInterfaceSettings().apply { saveData("ui_settings", this) }
|
||||
|
||||
override fun downloadTrigger(novelDownloadPackage: NovelDownloadPackage) {
|
||||
Log.e("downloadTrigger", novelDownloadPackage.link)
|
||||
|
@ -90,10 +91,24 @@ class NovelReadFragment : Fragment(),
|
|||
|
||||
override fun downloadedCheckWithStart(novel: ShowResponse): Boolean {
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
if(downloadsManager.queryDownload(Download(media.nameMAL ?: media.nameRomaji, novel.name, Download.Type.NOVEL))) {
|
||||
val file = File(context?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "${DownloadsManager.novelLocation}/${media.nameMAL ?: media.nameRomaji}/${novel.name}/0.epub")
|
||||
if (downloadsManager.queryDownload(
|
||||
Download(
|
||||
media.nameMAL ?: media.nameRomaji,
|
||||
novel.name,
|
||||
Download.Type.NOVEL
|
||||
)
|
||||
)
|
||||
) {
|
||||
val file = File(
|
||||
context?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
"${DownloadsManager.novelLocation}/${media.nameMAL ?: media.nameRomaji}/${novel.name}/0.epub"
|
||||
)
|
||||
if (!file.exists()) return false
|
||||
val fileUri = FileProvider.getUriForFile(requireContext(), "${requireContext().packageName}.provider", file)
|
||||
val fileUri = FileProvider.getUriForFile(
|
||||
requireContext(),
|
||||
"${requireContext().packageName}.provider",
|
||||
file
|
||||
)
|
||||
val intent = Intent(context, NovelReaderActivity::class.java).apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
setDataAndType(fileUri, "application/epub+zip")
|
||||
|
@ -108,12 +123,24 @@ class NovelReadFragment : Fragment(),
|
|||
|
||||
override fun downloadedCheck(novel: ShowResponse): Boolean {
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
return downloadsManager.queryDownload(Download(media.nameMAL ?: media.nameRomaji, novel.name, Download.Type.NOVEL))
|
||||
return downloadsManager.queryDownload(
|
||||
Download(
|
||||
media.nameMAL ?: media.nameRomaji,
|
||||
novel.name,
|
||||
Download.Type.NOVEL
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun deleteDownload(novel: ShowResponse) {
|
||||
val downloadsManager = Injekt.get<DownloadsManager>()
|
||||
downloadsManager.removeDownload(Download(media.nameMAL ?: media.nameRomaji, novel.name, Download.Type.NOVEL))
|
||||
downloadsManager.removeDownload(
|
||||
Download(
|
||||
media.nameMAL ?: media.nameRomaji,
|
||||
novel.name,
|
||||
Download.Type.NOVEL
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val downloadStatusReceiver = object : BroadcastReceiver() {
|
||||
|
@ -126,18 +153,21 @@ class NovelReadFragment : Fragment(),
|
|||
novelResponseAdapter.startDownload(it)
|
||||
}
|
||||
}
|
||||
|
||||
ACTION_DOWNLOAD_FINISHED -> {
|
||||
val link = intent.getStringExtra(EXTRA_NOVEL_LINK)
|
||||
link?.let {
|
||||
novelResponseAdapter.stopDownload(it)
|
||||
}
|
||||
}
|
||||
|
||||
ACTION_DOWNLOAD_FAILED -> {
|
||||
val link = intent.getStringExtra(EXTRA_NOVEL_LINK)
|
||||
link?.let {
|
||||
novelResponseAdapter.purgeDownload(it)
|
||||
}
|
||||
}
|
||||
|
||||
ACTION_DOWNLOAD_PROGRESS -> {
|
||||
val link = intent.getStringExtra(EXTRA_NOVEL_LINK)
|
||||
val progress = intent.getIntExtra("progress", 0)
|
||||
|
@ -159,7 +189,12 @@ class NovelReadFragment : Fragment(),
|
|||
addAction(ACTION_DOWNLOAD_PROGRESS)
|
||||
}
|
||||
|
||||
ContextCompat.registerReceiver(requireContext(), downloadStatusReceiver, intentFilter ,ContextCompat.RECEIVER_EXPORTED)
|
||||
ContextCompat.registerReceiver(
|
||||
requireContext(),
|
||||
downloadStatusReceiver,
|
||||
intentFilter,
|
||||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
|
||||
|
||||
|
@ -179,8 +214,13 @@ class NovelReadFragment : Fragment(),
|
|||
val sel = media.selected
|
||||
searchQuery = sel?.server ?: media.name ?: media.nameRomaji
|
||||
headerAdapter = NovelReadAdapter(media, this, model.novelSources)
|
||||
novelResponseAdapter = NovelResponseAdapter(this, this, this) // probably a better way to do this but it works
|
||||
binding.animeSourceRecycler.adapter = ConcatAdapter(headerAdapter, novelResponseAdapter)
|
||||
novelResponseAdapter = NovelResponseAdapter(
|
||||
this,
|
||||
this,
|
||||
this
|
||||
) // probably a better way to do this but it works
|
||||
binding.animeSourceRecycler.adapter =
|
||||
ConcatAdapter(headerAdapter, novelResponseAdapter)
|
||||
loaded = true
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
search(searchQuery, sel?.sourceIndex ?: 0, auto = sel?.server == null)
|
||||
|
@ -206,7 +246,7 @@ class NovelReadFragment : Fragment(),
|
|||
searchQuery = query
|
||||
headerAdapter.progress?.visibility = View.VISIBLE
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
if (auto || query=="") model.autoSearchNovels(media)
|
||||
if (auto || query == "") model.autoSearchNovels(media)
|
||||
else model.searchNovels(query, source)
|
||||
}
|
||||
searching = true
|
||||
|
|
|
@ -13,11 +13,22 @@ import ani.dantotsu.parsers.Book
|
|||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.tryWith
|
||||
|
||||
class UrlAdapter(private val urls: List<FileUrl>, val book: Book, val novel: String, val callback: BookDialog.Callback?) :
|
||||
class UrlAdapter(
|
||||
private val urls: List<FileUrl>,
|
||||
val book: Book,
|
||||
val novel: String,
|
||||
val callback: BookDialog.Callback?
|
||||
) :
|
||||
RecyclerView.Adapter<UrlAdapter.UrlViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UrlViewHolder {
|
||||
return UrlViewHolder(ItemUrlBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
return UrlViewHolder(
|
||||
ItemUrlBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
|
|
|
@ -27,6 +27,7 @@ import ani.dantotsu.databinding.ActivityNovelReaderBinding
|
|||
import ani.dantotsu.hideSystemBars
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.others.ImageViewDialog
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.saveData
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.CurrentNovelReaderSettings
|
||||
|
@ -35,7 +36,6 @@ import ani.dantotsu.settings.NovelReaderSettings
|
|||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.tryWith
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.vipulog.ebookreader.Book
|
||||
|
@ -161,7 +161,8 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
|
||||
binding.novelReaderBack.setOnClickListener { finish() }
|
||||
binding.novelReaderSettings.setSafeOnClickListener {
|
||||
NovelReaderSettingsDialogFragment.newInstance().show(supportFragmentManager, NovelReaderSettingsDialogFragment.TAG)
|
||||
NovelReaderSettingsDialogFragment.newInstance()
|
||||
.show(supportFragmentManager, NovelReaderSettingsDialogFragment.TAG)
|
||||
}
|
||||
|
||||
val gestureDetector = GestureDetectorCompat(this, object : GesturesListener() {
|
||||
|
@ -233,14 +234,21 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
binding.novelReaderSource.text = book.author?.joinToString(", ")
|
||||
|
||||
val tocLabels = book.toc.map { it.label ?: "" }
|
||||
binding.novelReaderChapterSelect.adapter = NoPaddingArrayAdapter(this, R.layout.item_dropdown, tocLabels)
|
||||
binding.novelReaderChapterSelect.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
binding.bookReader.goto(book.toc[position].href)
|
||||
}
|
||||
binding.novelReaderChapterSelect.adapter =
|
||||
NoPaddingArrayAdapter(this, R.layout.item_dropdown, tocLabels)
|
||||
binding.novelReaderChapterSelect.onItemSelectedListener =
|
||||
object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(
|
||||
parent: AdapterView<*>?,
|
||||
view: View?,
|
||||
position: Int,
|
||||
id: Long
|
||||
) {
|
||||
binding.bookReader.goto(book.toc[position].href)
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
|
||||
binding.bookReader.getAppearance {
|
||||
currentTheme = it
|
||||
|
@ -295,7 +303,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
private var onVolumeDown: (() -> Unit)? = null
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
return when (event.keyCode) {
|
||||
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_PAGE_UP -> {
|
||||
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_PAGE_UP -> {
|
||||
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP)
|
||||
if (!settings.default.volumeButtons)
|
||||
return false
|
||||
|
@ -315,7 +323,7 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
} else false
|
||||
}
|
||||
|
||||
else -> {
|
||||
else -> {
|
||||
super.dispatchKeyEvent(event)
|
||||
}
|
||||
}
|
||||
|
@ -326,10 +334,11 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
saveData("${sanitizedBookId}_current_settings", settings.default)
|
||||
hideBars()
|
||||
|
||||
currentTheme = themes.first { it.name.equals(settings.default.currentThemeName, ignoreCase = true) }
|
||||
currentTheme =
|
||||
themes.first { it.name.equals(settings.default.currentThemeName, ignoreCase = true) }
|
||||
|
||||
when (settings.default.layout) {
|
||||
CurrentNovelReaderSettings.Layouts.PAGED -> {
|
||||
CurrentNovelReaderSettings.Layouts.PAGED -> {
|
||||
currentTheme?.flow = ReaderFlow.PAGINATED
|
||||
}
|
||||
|
||||
|
@ -340,9 +349,10 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
|
||||
when (settings.default.dualPageMode) {
|
||||
CurrentReaderSettings.DualPageModes.No -> currentTheme?.maxColumnCount = 1
|
||||
CurrentReaderSettings.DualPageModes.No -> currentTheme?.maxColumnCount = 1
|
||||
CurrentReaderSettings.DualPageModes.Automatic -> currentTheme?.maxColumnCount = 2
|
||||
CurrentReaderSettings.DualPageModes.Force -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
CurrentReaderSettings.DualPageModes.Force -> requestedOrientation =
|
||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
}
|
||||
|
||||
currentTheme?.lineHeight = settings.default.lineHeight
|
||||
|
@ -393,7 +403,8 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
isContVisible = false
|
||||
if (!isAnimating) {
|
||||
isAnimating = true
|
||||
ObjectAnimator.ofFloat(binding.novelReaderCont, "alpha", 1f, 0f).setDuration(controllerDuration).start()
|
||||
ObjectAnimator.ofFloat(binding.novelReaderCont, "alpha", 1f, 0f)
|
||||
.setDuration(controllerDuration).start()
|
||||
ObjectAnimator.ofFloat(binding.novelReaderBottomCont, "translationY", 0f, 128f)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
ObjectAnimator.ofFloat(binding.novelReaderTopLayout, "translationY", 0f, -128f)
|
||||
|
@ -403,7 +414,8 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
} else {
|
||||
isContVisible = true
|
||||
binding.novelReaderCont.visibility = View.VISIBLE
|
||||
ObjectAnimator.ofFloat(binding.novelReaderCont, "alpha", 0f, 1f).setDuration(controllerDuration).start()
|
||||
ObjectAnimator.ofFloat(binding.novelReaderCont, "alpha", 0f, 1f)
|
||||
.setDuration(controllerDuration).start()
|
||||
ObjectAnimator.ofFloat(binding.novelReaderTopLayout, "translationY", -128f, 0f)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
ObjectAnimator.ofFloat(binding.novelReaderBottomCont, "translationY", 128f, 0f)
|
||||
|
@ -418,7 +430,10 @@ class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
|||
val displayCutout = window.decorView.rootWindowInsets.displayCutout
|
||||
if (displayCutout != null) {
|
||||
if (displayCutout.boundingRects.size > 0) {
|
||||
notchHeight = min(displayCutout.boundingRects[0].width(), displayCutout.boundingRects[0].height())
|
||||
notchHeight = min(
|
||||
displayCutout.boundingRects[0].width(),
|
||||
displayCutout.boundingRects[0].height()
|
||||
)
|
||||
applyNotchMargin()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,11 @@ class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
private val binding get() = _binding!!
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = BottomSheetCurrentNovelReaderSettingsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -29,10 +33,16 @@ class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
val settings = activity.settings.default
|
||||
|
||||
val themeLabels = activity.themes.map { it.name }
|
||||
binding.themeSelect.adapter = NoPaddingArrayAdapter(activity, R.layout.item_dropdown, themeLabels)
|
||||
binding.themeSelect.adapter =
|
||||
NoPaddingArrayAdapter(activity, R.layout.item_dropdown, themeLabels)
|
||||
binding.themeSelect.setSelection(themeLabels.indexOfFirst { it == settings.currentThemeName })
|
||||
binding.themeSelect.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
override fun onItemSelected(
|
||||
parent: AdapterView<*>?,
|
||||
view: View?,
|
||||
position: Int,
|
||||
id: Long
|
||||
) {
|
||||
settings.currentThemeName = themeLabels[position]
|
||||
activity.applySettings()
|
||||
}
|
||||
|
@ -54,7 +64,8 @@ class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
selected.alpha = 0.33f
|
||||
selected = imageButton
|
||||
selected.alpha = 1f
|
||||
settings.layout = CurrentNovelReaderSettings.Layouts[index]?:CurrentNovelReaderSettings.Layouts.PAGED
|
||||
settings.layout = CurrentNovelReaderSettings.Layouts[index]
|
||||
?: CurrentNovelReaderSettings.Layouts.PAGED
|
||||
binding.layoutText.text = settings.layout.string
|
||||
activity.applySettings()
|
||||
}
|
||||
|
@ -75,7 +86,8 @@ class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
selectedDual.alpha = 0.33f
|
||||
selectedDual = imageButton
|
||||
selectedDual.alpha = 1f
|
||||
settings.dualPageMode = CurrentReaderSettings.DualPageModes[index] ?: CurrentReaderSettings.DualPageModes.Automatic
|
||||
settings.dualPageMode = CurrentReaderSettings.DualPageModes[index]
|
||||
?: CurrentReaderSettings.DualPageModes.Automatic
|
||||
binding.dualPageText.text = settings.dualPageMode.toString()
|
||||
activity.applySettings()
|
||||
}
|
||||
|
@ -164,19 +176,19 @@ class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
binding.useDarkTheme.isChecked = settings.useDarkTheme
|
||||
binding.useDarkTheme.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.useDarkTheme.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.useDarkTheme = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.keepScreenOn.isChecked = settings.keepScreenOn
|
||||
binding.keepScreenOn.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.keepScreenOn.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.keepScreenOn = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.volumeButton.isChecked = settings.volumeButtons
|
||||
binding.volumeButton.setOnCheckedChangeListener { _,isChecked ->
|
||||
binding.volumeButton.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.volumeButtons = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
@ -189,7 +201,7 @@ class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
|
||||
companion object{
|
||||
companion object {
|
||||
fun newInstance() = NovelReaderSettingsDialogFragment()
|
||||
const val TAG = "NovelReaderSettingsDialogFragment"
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ import ani.dantotsu.R
|
|||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.databinding.ActivityListBinding
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.others.LangSet
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -34,14 +34,18 @@ class ListActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
LangSet.setLocale(this)
|
||||
ThemeManager(this).applyTheme()
|
||||
ThemeManager(this).applyTheme()
|
||||
binding = ActivityListBinding.inflate(layoutInflater)
|
||||
|
||||
val typedValue = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValue, true)
|
||||
val primaryColor = typedValue.data
|
||||
val typedValue2 = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorOnBackground, typedValue2, true)
|
||||
theme.resolveAttribute(
|
||||
com.google.android.material.R.attr.colorOnBackground,
|
||||
typedValue2,
|
||||
true
|
||||
)
|
||||
val titleTextColor = typedValue2.data
|
||||
val typedValue3 = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue3, true)
|
||||
|
@ -63,33 +67,50 @@ ThemeManager(this).applyTheme()
|
|||
ContextCompat.getColor(this, R.color.nav_bg_inv)
|
||||
binding.root.fitsSystemWindows = true
|
||||
|
||||
}else{
|
||||
} else {
|
||||
binding.root.fitsSystemWindows = false
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||
window.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
}
|
||||
setContentView(binding.root)
|
||||
|
||||
val anime = intent.getBooleanExtra("anime", true)
|
||||
binding.listTitle.text = intent.getStringExtra("username") + "'s " + (if (anime) "Anime" else "Manga") + " List"
|
||||
binding.listTitle.text =
|
||||
intent.getStringExtra("username") + "'s " + (if (anime) "Anime" else "Manga") + " List"
|
||||
|
||||
binding.listTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
this@ListActivity.selectedTabIdx = tab?.position ?: 0
|
||||
}
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) { }
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) { }
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {}
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {}
|
||||
})
|
||||
|
||||
val model: ListViewModel by viewModels()
|
||||
model.getLists().observe(this) {
|
||||
val defaultKeys = listOf("Reading", "Watching", "Completed", "Paused", "Dropped", "Planning", "Favourites", "Rewatching", "Rereading", "All")
|
||||
val userKeys : Array<String> = resources.getStringArray(R.array.keys)
|
||||
val defaultKeys = listOf(
|
||||
"Reading",
|
||||
"Watching",
|
||||
"Completed",
|
||||
"Paused",
|
||||
"Dropped",
|
||||
"Planning",
|
||||
"Favourites",
|
||||
"Rewatching",
|
||||
"Rereading",
|
||||
"All"
|
||||
)
|
||||
val userKeys: Array<String> = resources.getStringArray(R.array.keys)
|
||||
|
||||
if (it != null) {
|
||||
binding.listProgressBar.visibility = View.GONE
|
||||
binding.listViewPager.adapter = ListViewPagerAdapter(it.size, false,this)
|
||||
val keys = it.keys.toList().map { key -> userKeys.getOrNull(defaultKeys.indexOf(key))?: key }
|
||||
binding.listViewPager.adapter = ListViewPagerAdapter(it.size, false, this)
|
||||
val keys = it.keys.toList()
|
||||
.map { key -> userKeys.getOrNull(defaultKeys.indexOf(key)) ?: key }
|
||||
val values = it.values.toList()
|
||||
val savedTab = this.selectedTabIdx
|
||||
TabLayoutMediator(binding.listTabLayout, binding.listViewPager) { tab, position ->
|
||||
|
@ -103,32 +124,43 @@ ThemeManager(this).applyTheme()
|
|||
live.observe(this) {
|
||||
if (it) {
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) { model.loadLists(anime, intent.getIntExtra("userId", 0)) }
|
||||
withContext(Dispatchers.IO) {
|
||||
model.loadLists(
|
||||
anime,
|
||||
intent.getIntExtra("userId", 0)
|
||||
)
|
||||
}
|
||||
live.postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.listSort.setOnClickListener {
|
||||
val popup = PopupMenu(this, it)
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
val sort = when (item.itemId) {
|
||||
R.id.score -> "score"
|
||||
R.id.title -> "title"
|
||||
R.id.updated -> "updatedAt"
|
||||
R.id.release -> "release"
|
||||
else -> null
|
||||
}
|
||||
binding.listSort.setOnClickListener {
|
||||
val popup = PopupMenu(this, it)
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
val sort = when (item.itemId) {
|
||||
R.id.score -> "score"
|
||||
R.id.title -> "title"
|
||||
R.id.updated -> "updatedAt"
|
||||
R.id.release -> "release"
|
||||
else -> null
|
||||
}
|
||||
|
||||
binding.listProgressBar.visibility = View.VISIBLE
|
||||
binding.listViewPager.adapter = null
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) { model.loadLists(anime, intent.getIntExtra("userId", 0), sort) }
|
||||
}
|
||||
true
|
||||
}
|
||||
popup.inflate(R.menu.list_sort_menu)
|
||||
popup.show()
|
||||
}
|
||||
binding.listProgressBar.visibility = View.VISIBLE
|
||||
binding.listViewPager.adapter = null
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
model.loadLists(
|
||||
anime,
|
||||
intent.getIntExtra("userId", 0),
|
||||
sort
|
||||
)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
popup.inflate(R.menu.list_sort_menu)
|
||||
popup.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ import ani.dantotsu.databinding.FragmentListBinding
|
|||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaAdaptor
|
||||
import ani.dantotsu.media.OtherDetailsViewModel
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.others.LangSet
|
||||
|
||||
class ListFragment : Fragment() {
|
||||
private var _binding: FragmentListBinding? = null
|
||||
|
@ -29,7 +27,11 @@ class ListFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentListBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
@ -42,7 +44,10 @@ class ListFragment : Fragment() {
|
|||
if (grid != null && list != null) {
|
||||
val adapter = MediaAdaptor(if (grid!!) 0 else 1, list!!, requireActivity(), true)
|
||||
binding.listRecyclerView.layoutManager =
|
||||
GridLayoutManager(requireContext(), if (grid!!) (screenWidth / 124f).toInt() else 1)
|
||||
GridLayoutManager(
|
||||
requireContext(),
|
||||
if (grid!!) (screenWidth / 124f).toInt() else 1
|
||||
)
|
||||
binding.listRecyclerView.adapter = adapter
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,13 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
|
||||
class ListViewPagerAdapter(private val size: Int, private val calendar: Boolean, fragment: FragmentActivity) :
|
||||
class ListViewPagerAdapter(
|
||||
private val size: Int,
|
||||
private val calendar: Boolean,
|
||||
fragment: FragmentActivity
|
||||
) :
|
||||
FragmentStateAdapter(fragment) {
|
||||
override fun getItemCount(): Int = size
|
||||
override fun createFragment(position: Int): Fragment = ListFragment.newInstance(position, calendar)
|
||||
override fun createFragment(position: Int): Fragment =
|
||||
ListFragment.newInstance(position, calendar)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue