offline anime
This commit is contained in:
parent
52dadf34cf
commit
98cb11e841
17 changed files with 630 additions and 22 deletions
|
@ -14,6 +14,7 @@ import android.provider.Settings
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowManager
|
||||||
import android.view.animation.AnticipateInterpolator
|
import android.view.animation.AnticipateInterpolator
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
package ani.dantotsu.download.anime
|
||||||
|
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.BaseAdapter
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.download.anime.OfflineAnimeModel
|
||||||
|
import ani.dantotsu.download.anime.OfflineAnimeSearchListener
|
||||||
|
|
||||||
|
|
||||||
|
class OfflineAnimeAdapter(
|
||||||
|
private val context: Context,
|
||||||
|
private var items: List<OfflineAnimeModel>,
|
||||||
|
private val searchListener: OfflineAnimeSearchListener
|
||||||
|
) : BaseAdapter() {
|
||||||
|
private val inflater: LayoutInflater =
|
||||||
|
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||||
|
private var originalItems: List<OfflineAnimeModel> = items
|
||||||
|
private var style =
|
||||||
|
context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getInt("offline_view", 0)
|
||||||
|
|
||||||
|
override fun getCount(): Int {
|
||||||
|
return items.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItem(position: Int): Any {
|
||||||
|
return items[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemId(position: Int): Long {
|
||||||
|
return position.toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||||
|
|
||||||
|
val view: View = convertView ?: when (style) {
|
||||||
|
0 -> inflater.inflate(R.layout.item_media_large, parent, false) // large view
|
||||||
|
1 -> inflater.inflate(R.layout.item_media_compact, parent, false) // compact view
|
||||||
|
else -> inflater.inflate(R.layout.item_media_compact, parent, false) // compact view
|
||||||
|
}
|
||||||
|
|
||||||
|
val item = getItem(position) as OfflineAnimeModel
|
||||||
|
val imageView = view.findViewById<ImageView>(R.id.itemCompactImage)
|
||||||
|
val titleTextView = view.findViewById<TextView>(R.id.itemCompactTitle)
|
||||||
|
val itemScore = view.findViewById<TextView>(R.id.itemCompactScore)
|
||||||
|
val itemScoreBG = view.findViewById<View>(R.id.itemCompactScoreBG)
|
||||||
|
val ongoing = view.findViewById<CardView>(R.id.itemCompactOngoing)
|
||||||
|
val totalchapter = view.findViewById<TextView>(R.id.itemCompactTotal)
|
||||||
|
val typeimage = view.findViewById<ImageView>(R.id.itemCompactTypeImage)
|
||||||
|
val type = view.findViewById<TextView>(R.id.itemCompactRelation)
|
||||||
|
val typeView = view.findViewById<LinearLayout>(R.id.itemCompactType)
|
||||||
|
|
||||||
|
if (style == 0) {
|
||||||
|
val bannerView = view.findViewById<ImageView>(R.id.itemCompactBanner) // for large view
|
||||||
|
val chapters = view.findViewById<TextView>(R.id.itemTotal)
|
||||||
|
chapters.text = " Chapters"
|
||||||
|
bannerView.setImageURI(item.banner)
|
||||||
|
totalchapter.text = item.totalEpisode
|
||||||
|
} else if (style == 1) {
|
||||||
|
val readchapter =
|
||||||
|
view.findViewById<TextView>(R.id.itemCompactUserProgress) // for compact view
|
||||||
|
readchapter.text = item.watchedEpisode
|
||||||
|
totalchapter.text = " | " + item.totalEpisode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind item data to the views
|
||||||
|
typeimage.setImageResource(R.drawable.ic_round_movie_filter_24)
|
||||||
|
type.text = item.type
|
||||||
|
typeView.visibility = View.VISIBLE
|
||||||
|
imageView.setImageURI(item.image)
|
||||||
|
titleTextView.text = item.title
|
||||||
|
itemScore.text = item.score
|
||||||
|
|
||||||
|
if (item.isOngoing) {
|
||||||
|
ongoing.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
ongoing.visibility = View.GONE
|
||||||
|
}
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSearchQuery(query: String) {
|
||||||
|
// Implement the filtering logic here, for example:
|
||||||
|
items = if (query.isEmpty()) {
|
||||||
|
// Return the original list if the query is empty
|
||||||
|
originalItems
|
||||||
|
} else {
|
||||||
|
// Filter the list based on the query
|
||||||
|
originalItems.filter { it.title.contains(query, ignoreCase = true) }
|
||||||
|
}
|
||||||
|
notifyDataSetChanged() // Notify the adapter that the data set has changed
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setItems(items: List<OfflineAnimeModel>) {
|
||||||
|
this.items = items
|
||||||
|
this.originalItems = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notifyNewGrid() {
|
||||||
|
style =
|
||||||
|
context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getInt("offline_view", 0)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,439 @@
|
||||||
|
package ani.dantotsu.download.anime
|
||||||
|
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Environment
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.animation.AlphaAnimation
|
||||||
|
import android.view.animation.LayoutAnimationController
|
||||||
|
import android.view.animation.OvershootInterpolator
|
||||||
|
import android.widget.AbsListView
|
||||||
|
import android.widget.AutoCompleteTextView
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.GridView
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.widget.ThemedSpinnerAdapter.Helper
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
|
import androidx.core.view.updatePaddingRelative
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.currActivity
|
||||||
|
import ani.dantotsu.currContext
|
||||||
|
import ani.dantotsu.download.DownloadedType
|
||||||
|
import ani.dantotsu.download.DownloadsManager
|
||||||
|
import ani.dantotsu.initActivity
|
||||||
|
import ani.dantotsu.logger
|
||||||
|
import ani.dantotsu.media.Media
|
||||||
|
import ani.dantotsu.media.MediaDetailsActivity
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.px
|
||||||
|
import ani.dantotsu.setSafeOnClickListener
|
||||||
|
import ani.dantotsu.settings.SettingsDialogFragment
|
||||||
|
import ani.dantotsu.snackString
|
||||||
|
import ani.dantotsu.statusBarHeight
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import com.google.gson.InstanceCreator
|
||||||
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
|
import eu.kanade.tachiyomi.animesource.model.SAnimeImpl
|
||||||
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
|
import eu.kanade.tachiyomi.animesource.model.SEpisodeImpl
|
||||||
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
|
import eu.kanade.tachiyomi.source.model.SChapterImpl
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
|
||||||
|
|
||||||
|
private val downloadManager = Injekt.get<DownloadsManager>()
|
||||||
|
private var downloads: List<OfflineAnimeModel> = listOf()
|
||||||
|
private lateinit var gridView: GridView
|
||||||
|
private lateinit var adapter: OfflineAnimeAdapter
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class) override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
val view = inflater.inflate(R.layout.fragment_manga_offline, container, false)
|
||||||
|
|
||||||
|
val textInputLayout = view.findViewById<TextInputLayout>(R.id.offlineMangaSearchBar)
|
||||||
|
textInputLayout.hint = "Anime"
|
||||||
|
val currentColor = textInputLayout.boxBackgroundColor
|
||||||
|
val semiTransparentColor = (currentColor and 0x00FFFFFF) or 0xA8000000.toInt()
|
||||||
|
textInputLayout.boxBackgroundColor = semiTransparentColor
|
||||||
|
val materialCardView = view.findViewById<MaterialCardView>(R.id.offlineMangaAvatarContainer)
|
||||||
|
materialCardView.setCardBackgroundColor(semiTransparentColor)
|
||||||
|
val typedValue = TypedValue()
|
||||||
|
requireContext().theme?.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
|
||||||
|
val color = typedValue.data
|
||||||
|
|
||||||
|
val animeTitleContainer = view.findViewById<LinearLayout>(R.id.animeTitleContainer)
|
||||||
|
animeTitleContainer.updatePadding(top = statusBarHeight)
|
||||||
|
|
||||||
|
val animeUserAvatar = view.findViewById<ShapeableImageView>(R.id.offlineMangaUserAvatar)
|
||||||
|
animeUserAvatar.setSafeOnClickListener {
|
||||||
|
val dialogFragment =
|
||||||
|
SettingsDialogFragment.newInstance2(SettingsDialogFragment.Companion.PageType2.OfflineANIME)
|
||||||
|
dialogFragment.show((it.context as AppCompatActivity).supportFragmentManager, "dialog")
|
||||||
|
}
|
||||||
|
|
||||||
|
val colorOverflow = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||||
|
?.getBoolean("colorOverflow", false) ?: false
|
||||||
|
if (!colorOverflow) {
|
||||||
|
textInputLayout.boxBackgroundColor = (color and 0x00FFFFFF) or 0x28000000.toInt()
|
||||||
|
materialCardView.setCardBackgroundColor((color and 0x00FFFFFF) or 0x28000000.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
val searchView = view.findViewById<AutoCompleteTextView>(R.id.animeSearchBarText)
|
||||||
|
searchView.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
|
onSearchQuery(s.toString())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
var style = context?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||||
|
?.getInt("offline_view", 0)
|
||||||
|
val layoutList = view.findViewById<ImageView>(R.id.downloadedList)
|
||||||
|
val layoutcompact = view.findViewById<ImageView>(R.id.downloadedGrid)
|
||||||
|
var selected = when (style) {
|
||||||
|
0 -> layoutList
|
||||||
|
1 -> layoutcompact
|
||||||
|
else -> layoutList
|
||||||
|
}
|
||||||
|
selected.alpha = 1f
|
||||||
|
|
||||||
|
fun selected(it: ImageView) {
|
||||||
|
selected.alpha = 0.33f
|
||||||
|
selected = it
|
||||||
|
selected.alpha = 1f
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutList.setOnClickListener {
|
||||||
|
selected(it as ImageView)
|
||||||
|
style = 0
|
||||||
|
context?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)?.edit()
|
||||||
|
?.putInt("offline_view", style!!)?.apply()
|
||||||
|
gridView.visibility = View.GONE
|
||||||
|
gridView = view.findViewById(R.id.gridView)
|
||||||
|
gridView.adapter = adapter
|
||||||
|
gridView.scheduleLayoutAnimation()
|
||||||
|
gridView.visibility = View.VISIBLE
|
||||||
|
adapter.notifyNewGrid()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutcompact.setOnClickListener {
|
||||||
|
selected(it as ImageView)
|
||||||
|
style = 1
|
||||||
|
context?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)?.edit()
|
||||||
|
?.putInt("offline_view", style!!)?.apply()
|
||||||
|
gridView.visibility = View.GONE
|
||||||
|
gridView = view.findViewById(R.id.gridView1)
|
||||||
|
gridView.adapter = adapter
|
||||||
|
gridView.scheduleLayoutAnimation()
|
||||||
|
gridView.visibility = View.VISIBLE
|
||||||
|
adapter.notifyNewGrid()
|
||||||
|
}
|
||||||
|
|
||||||
|
gridView =
|
||||||
|
if (style == 0) view.findViewById(R.id.gridView) else view.findViewById(R.id.gridView1)
|
||||||
|
gridView.visibility = View.VISIBLE
|
||||||
|
getDownloads()
|
||||||
|
|
||||||
|
val fadeIn = AlphaAnimation(0f, 1f)
|
||||||
|
fadeIn.duration = 200 // animations pog
|
||||||
|
val animation = LayoutAnimationController(fadeIn)
|
||||||
|
|
||||||
|
gridView.layoutAnimation = animation
|
||||||
|
adapter = OfflineAnimeAdapter(requireContext(), downloads, this)
|
||||||
|
gridView.adapter = adapter
|
||||||
|
gridView.scheduleLayoutAnimation()
|
||||||
|
gridView.setOnItemClickListener { parent, view, position, id ->
|
||||||
|
// Get the OfflineAnimeModel that was clicked
|
||||||
|
val item = adapter.getItem(position) as OfflineAnimeModel
|
||||||
|
val media =
|
||||||
|
downloadManager.animeDownloadedTypes.firstOrNull { it.title == item.title }
|
||||||
|
media?.let {
|
||||||
|
startActivity(
|
||||||
|
Intent(requireContext(), MediaDetailsActivity::class.java)
|
||||||
|
.putExtra("media", getMedia(it))
|
||||||
|
.putExtra("download", true)
|
||||||
|
)
|
||||||
|
} ?: run {
|
||||||
|
snackString("no media found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val total = view.findViewById<TextView>(R.id.total)
|
||||||
|
total.text =
|
||||||
|
if (gridView.count > 0) "Anime (${gridView.count})" else "Empty List"
|
||||||
|
gridView.setOnItemLongClickListener { parent, view, position, id ->
|
||||||
|
// Get the OfflineAnimeModel that was clicked
|
||||||
|
val item = adapter.getItem(position) as OfflineAnimeModel
|
||||||
|
val type: DownloadedType.Type =
|
||||||
|
DownloadedType.Type.ANIME
|
||||||
|
|
||||||
|
// Alert dialog to confirm deletion
|
||||||
|
val builder =
|
||||||
|
androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup)
|
||||||
|
builder.setTitle("Delete ${item.title}?")
|
||||||
|
builder.setMessage("Are you sure you want to delete ${item.title}?")
|
||||||
|
builder.setPositiveButton("Yes") { _, _ ->
|
||||||
|
downloadManager.removeMedia(item.title, type)
|
||||||
|
val mediaIds = requireContext().getSharedPreferences(getString(R.string.anime_downloads), Context.MODE_PRIVATE)
|
||||||
|
?.all?.filter { it.key.contains(item.title) }?.values ?: emptySet()
|
||||||
|
for (mediaId in mediaIds) {
|
||||||
|
ani.dantotsu.download.video.Helper.downloadManager(requireContext())
|
||||||
|
.removeDownload(mediaId.toString())
|
||||||
|
}
|
||||||
|
getDownloads()
|
||||||
|
adapter.setItems(downloads)
|
||||||
|
}
|
||||||
|
builder.setNegativeButton("No") { _, _ ->
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
val dialog = builder.show()
|
||||||
|
dialog.window?.setDimAmount(0.8f)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
view.rootView.fitsSystemWindows = true
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSearchQuery(query: String) {
|
||||||
|
adapter.onSearchQuery(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
var height = statusBarHeight
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
val displayCutout = activity?.window?.decorView?.rootWindowInsets?.displayCutout
|
||||||
|
if (displayCutout != null) {
|
||||||
|
if (displayCutout.boundingRects.size > 0) {
|
||||||
|
height = max(
|
||||||
|
statusBarHeight,
|
||||||
|
min(
|
||||||
|
displayCutout.boundingRects[0].width(),
|
||||||
|
displayCutout.boundingRects[0].height()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val mangaRefresh = view.findViewById<FrameLayout>(R.id.mangaRefresh)
|
||||||
|
mangaRefresh.updatePaddingRelative(bottom = navBarHeight + 160f.px)
|
||||||
|
val scrollTop = view.findViewById<CardView>(R.id.mangaPageScrollTop)
|
||||||
|
val visible = false
|
||||||
|
|
||||||
|
fun animate() {
|
||||||
|
val start = if (visible) 0f else 1f
|
||||||
|
val end = if (!visible) 0f else 1f
|
||||||
|
ObjectAnimator.ofFloat(scrollTop, "scaleX", start, end).apply {
|
||||||
|
duration = 300
|
||||||
|
interpolator = OvershootInterpolator(2f)
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
ObjectAnimator.ofFloat(scrollTop, "scaleY", start, end).apply {
|
||||||
|
duration = 300
|
||||||
|
interpolator = OvershootInterpolator(2f)
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollTop.setOnClickListener {
|
||||||
|
gridView.smoothScrollToPosition(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming 'scrollTop' is a view that you want to hide/show
|
||||||
|
scrollTop.visibility = View.GONE
|
||||||
|
|
||||||
|
gridView.setOnScrollListener(object : AbsListView.OnScrollListener {
|
||||||
|
override fun onScrollStateChanged(view: AbsListView, scrollState: Int) {
|
||||||
|
// Implement behavior for different scroll states if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScroll(
|
||||||
|
view: AbsListView,
|
||||||
|
firstVisibleItem: Int,
|
||||||
|
visibleItemCount: Int,
|
||||||
|
totalItemCount: Int
|
||||||
|
) {
|
||||||
|
val first = view.getChildAt(0)
|
||||||
|
val visibility = first != null && first.top < -height
|
||||||
|
scrollTop.visibility = if (visibility) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
initActivity(requireActivity())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
getDownloads()
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
downloads = listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
downloads = listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
downloads = listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getDownloads() {
|
||||||
|
downloads = listOf()
|
||||||
|
val animeTitles = downloadManager.animeDownloadedTypes.map { it.title }.distinct()
|
||||||
|
val newAnimeDownloads = mutableListOf<OfflineAnimeModel>()
|
||||||
|
for (title in animeTitles) {
|
||||||
|
val _downloads = downloadManager.animeDownloadedTypes.filter { it.title == title }
|
||||||
|
val download = _downloads.first()
|
||||||
|
val offlineAnimeModel = loadOfflineAnimeModel(download)
|
||||||
|
newAnimeDownloads += offlineAnimeModel
|
||||||
|
}
|
||||||
|
downloads = newAnimeDownloads
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMedia(downloadedType: DownloadedType): Media? {
|
||||||
|
val type = if (downloadedType.type == DownloadedType.Type.ANIME) {
|
||||||
|
"Anime"
|
||||||
|
} else if (downloadedType.type == DownloadedType.Type.MANGA) {
|
||||||
|
"Manga"
|
||||||
|
} else {
|
||||||
|
"Novel"
|
||||||
|
}
|
||||||
|
val directory = File(
|
||||||
|
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||||
|
"Dantotsu/$type/${downloadedType.title}"
|
||||||
|
)
|
||||||
|
//load media.json and convert to media class with gson
|
||||||
|
return try {
|
||||||
|
val gson = GsonBuilder()
|
||||||
|
.registerTypeAdapter(SChapter::class.java, InstanceCreator<SChapter> {
|
||||||
|
SChapterImpl() // Provide an instance of SChapterImpl
|
||||||
|
})
|
||||||
|
.registerTypeAdapter(SAnime::class.java, InstanceCreator<SAnime> {
|
||||||
|
SAnimeImpl() // Provide an instance of SAnimeImpl
|
||||||
|
})
|
||||||
|
.registerTypeAdapter(SEpisode::class.java, InstanceCreator<SEpisode> {
|
||||||
|
SEpisodeImpl() // Provide an instance of SEpisodeImpl
|
||||||
|
})
|
||||||
|
.create()
|
||||||
|
val media = File(directory, "media.json")
|
||||||
|
val mediaJson = media.readText()
|
||||||
|
gson.fromJson(mediaJson, Media::class.java)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger("Error loading media.json: ${e.message}")
|
||||||
|
logger(e.printStackTrace())
|
||||||
|
FirebaseCrashlytics.getInstance().recordException(e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadOfflineAnimeModel(downloadedType: DownloadedType): OfflineAnimeModel {
|
||||||
|
val type = if (downloadedType.type == DownloadedType.Type.MANGA) {
|
||||||
|
"Manga"
|
||||||
|
} else if (downloadedType.type == DownloadedType.Type.ANIME) {
|
||||||
|
"Anime"
|
||||||
|
} else {
|
||||||
|
"Novel"
|
||||||
|
}
|
||||||
|
val directory = File(
|
||||||
|
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||||
|
"Dantotsu/$type/${downloadedType.title}"
|
||||||
|
)
|
||||||
|
//load media.json and convert to media class with gson
|
||||||
|
try {
|
||||||
|
val media = File(directory, "media.json")
|
||||||
|
val mediaJson = media.readText()
|
||||||
|
val mediaModel = getMedia(downloadedType)!!
|
||||||
|
val cover = File(directory, "cover.jpg")
|
||||||
|
val coverUri: Uri? = if (cover.exists()) {
|
||||||
|
Uri.fromFile(cover)
|
||||||
|
} else null
|
||||||
|
val banner = File(directory, "banner.jpg")
|
||||||
|
val bannerUri: Uri? = if (banner.exists()) {
|
||||||
|
Uri.fromFile(banner)
|
||||||
|
} else null
|
||||||
|
val title = mediaModel.nameMAL ?: mediaModel.nameRomaji
|
||||||
|
val score = ((if (mediaModel.userScore == 0) (mediaModel.meanScore
|
||||||
|
?: 0) else mediaModel.userScore) / 10.0).toString()
|
||||||
|
val isOngoing =
|
||||||
|
mediaModel.status == currActivity()!!.getString(R.string.status_releasing)
|
||||||
|
val isUserScored = mediaModel.userScore != 0
|
||||||
|
val readEpisode = (mediaModel.userProgress ?: "~").toString()
|
||||||
|
val totalEpisode = "${mediaModel.anime?.totalEpisodes ?: "??"}"
|
||||||
|
val chapters = " Chapters"
|
||||||
|
return OfflineAnimeModel(
|
||||||
|
title,
|
||||||
|
score,
|
||||||
|
totalEpisode,
|
||||||
|
readEpisode,
|
||||||
|
type,
|
||||||
|
chapters,
|
||||||
|
isOngoing,
|
||||||
|
isUserScored,
|
||||||
|
coverUri,
|
||||||
|
bannerUri
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger("Error loading media.json: ${e.message}")
|
||||||
|
logger(e.printStackTrace())
|
||||||
|
FirebaseCrashlytics.getInstance().recordException(e)
|
||||||
|
return OfflineAnimeModel(
|
||||||
|
"unknown",
|
||||||
|
"0",
|
||||||
|
"??",
|
||||||
|
"??",
|
||||||
|
"movie",
|
||||||
|
"hmm",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OfflineAnimeSearchListener {
|
||||||
|
fun onSearchQuery(query: String)
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package ani.dantotsu.download.anime
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
data class OfflineAnimeModel (
|
||||||
|
val title: String,
|
||||||
|
val score: String,
|
||||||
|
val totalEpisode: String,
|
||||||
|
val watchedEpisode: String,
|
||||||
|
val type: String,
|
||||||
|
val episodes: String,
|
||||||
|
val isOngoing: Boolean,
|
||||||
|
val isUserScored: Boolean,
|
||||||
|
val image: Uri?,
|
||||||
|
val banner: Uri?,
|
||||||
|
)
|
|
@ -61,12 +61,12 @@ class OfflineMangaAdapter(
|
||||||
val chapters = view.findViewById<TextView>(R.id.itemTotal)
|
val chapters = view.findViewById<TextView>(R.id.itemTotal)
|
||||||
chapters.text = " Chapters"
|
chapters.text = " Chapters"
|
||||||
bannerView.setImageURI(item.banner)
|
bannerView.setImageURI(item.banner)
|
||||||
totalchapter.text = item.totalchapter
|
totalchapter.text = item.totalChapter
|
||||||
} else if (style == 1) {
|
} else if (style == 1) {
|
||||||
val readchapter =
|
val readchapter =
|
||||||
view.findViewById<TextView>(R.id.itemCompactUserProgress) // for compact view
|
view.findViewById<TextView>(R.id.itemCompactUserProgress) // for compact view
|
||||||
readchapter.text = item.readchapter
|
readchapter.text = item.readChapter
|
||||||
totalchapter.text = " | " + item.totalchapter
|
totalchapter.text = " | " + item.totalChapter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind item data to the views
|
// Bind item data to the views
|
||||||
|
|
|
@ -18,11 +18,15 @@ import android.view.animation.LayoutAnimationController
|
||||||
import android.view.animation.OvershootInterpolator
|
import android.view.animation.OvershootInterpolator
|
||||||
import android.widget.AbsListView
|
import android.widget.AbsListView
|
||||||
import android.widget.AutoCompleteTextView
|
import android.widget.AutoCompleteTextView
|
||||||
|
import android.widget.FrameLayout
|
||||||
import android.widget.GridView
|
import android.widget.GridView
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
|
import androidx.core.view.updatePaddingRelative
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.currActivity
|
import ani.dantotsu.currActivity
|
||||||
|
@ -33,6 +37,8 @@ import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.logger
|
import ani.dantotsu.logger
|
||||||
import ani.dantotsu.media.Media
|
import ani.dantotsu.media.Media
|
||||||
import ani.dantotsu.media.MediaDetailsActivity
|
import ani.dantotsu.media.MediaDetailsActivity
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.px
|
||||||
import ani.dantotsu.setSafeOnClickListener
|
import ani.dantotsu.setSafeOnClickListener
|
||||||
import ani.dantotsu.settings.SettingsDialogFragment
|
import ani.dantotsu.settings.SettingsDialogFragment
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
|
@ -75,6 +81,9 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
||||||
requireContext().theme?.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
|
requireContext().theme?.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
|
||||||
val color = typedValue.data
|
val color = typedValue.data
|
||||||
|
|
||||||
|
val animeTitleContainer = view.findViewById<LinearLayout>(R.id.animeTitleContainer)
|
||||||
|
animeTitleContainer.updatePadding(top = statusBarHeight)
|
||||||
|
|
||||||
val animeUserAvatar = view.findViewById<ShapeableImageView>(R.id.offlineMangaUserAvatar)
|
val animeUserAvatar = view.findViewById<ShapeableImageView>(R.id.offlineMangaUserAvatar)
|
||||||
animeUserAvatar.setSafeOnClickListener {
|
animeUserAvatar.setSafeOnClickListener {
|
||||||
val dialogFragment =
|
val dialogFragment =
|
||||||
|
@ -204,6 +213,7 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
||||||
dialog.window?.setDimAmount(0.8f)
|
dialog.window?.setDimAmount(0.8f)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
view.rootView.fitsSystemWindows = true
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -230,8 +240,11 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val mangaRefresh = view.findViewById<FrameLayout>(R.id.mangaRefresh)
|
||||||
|
mangaRefresh.updatePaddingRelative(bottom = navBarHeight + 160f.px)
|
||||||
val scrollTop = view.findViewById<CardView>(R.id.mangaPageScrollTop)
|
val scrollTop = view.findViewById<CardView>(R.id.mangaPageScrollTop)
|
||||||
var visible = false
|
var visible = false
|
||||||
|
|
||||||
fun animate() {
|
fun animate() {
|
||||||
val start = if (visible) 0f else 1f
|
val start = if (visible) 0f else 1f
|
||||||
val end = if (!visible) 0f else 1f
|
val end = if (!visible) 0f else 1f
|
||||||
|
|
|
@ -5,8 +5,8 @@ import android.net.Uri
|
||||||
data class OfflineMangaModel(
|
data class OfflineMangaModel(
|
||||||
val title: String,
|
val title: String,
|
||||||
val score: String,
|
val score: String,
|
||||||
val totalchapter: String,
|
val totalChapter: String,
|
||||||
val readchapter: String,
|
val readChapter: String,
|
||||||
val type: String,
|
val type: String,
|
||||||
val chapters: String,
|
val chapters: String,
|
||||||
val isOngoing: Boolean,
|
val isOngoing: Boolean,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ani.dantotsu.home
|
package ani.dantotsu.home
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
@ -19,7 +20,9 @@ import androidx.lifecycle.Lifecycle
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.ZoomOutPageTransformer
|
import ani.dantotsu.ZoomOutPageTransformer
|
||||||
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.databinding.ActivityNoInternetBinding
|
import ani.dantotsu.databinding.ActivityNoInternetBinding
|
||||||
|
import ani.dantotsu.download.anime.OfflineAnimeFragment
|
||||||
import ani.dantotsu.download.manga.OfflineMangaFragment
|
import ani.dantotsu.download.manga.OfflineMangaFragment
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.loadData
|
import ani.dantotsu.loadData
|
||||||
|
@ -113,12 +116,11 @@ class NoInternet : AppCompatActivity() {
|
||||||
override fun getItemCount(): Int = 3
|
override fun getItemCount(): Int = 3
|
||||||
|
|
||||||
override fun createFragment(position: Int): Fragment {
|
override fun createFragment(position: Int): Fragment {
|
||||||
when (position) {
|
return when (position) {
|
||||||
0 -> return OfflineFragment()
|
0 -> OfflineAnimeFragment()
|
||||||
1 -> return OfflineFragment()
|
2 -> OfflineMangaFragment()
|
||||||
2 -> return OfflineMangaFragment()
|
else -> OfflineFragment()
|
||||||
}
|
}
|
||||||
return LoginFragment()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,6 +10,7 @@ import android.view.GestureDetector
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowManager
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator
|
import android.view.animation.AccelerateDecelerateInterpolator
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
@ -77,6 +78,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
||||||
ThemeManager(this).applyTheme(MediaSingleton.bitmap)
|
ThemeManager(this).applyTheme(MediaSingleton.bitmap)
|
||||||
MediaSingleton.bitmap = null
|
MediaSingleton.bitmap = null
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
binding = ActivityMediaBinding.inflate(layoutInflater)
|
binding = ActivityMediaBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
screenWidth = resources.displayMetrics.widthPixels.toFloat()
|
screenWidth = resources.displayMetrics.widthPixels.toFloat()
|
||||||
|
@ -85,8 +87,6 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
||||||
|
|
||||||
initActivity(this)
|
initActivity(this)
|
||||||
uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
||||||
if (!uiSettings.immersiveMode) this.window.statusBarColor =
|
|
||||||
ContextCompat.getColor(this, R.color.nav_bg_inv)
|
|
||||||
|
|
||||||
binding.mediaBanner.updateLayoutParams { height += statusBarHeight }
|
binding.mediaBanner.updateLayoutParams { height += statusBarHeight }
|
||||||
binding.mediaBannerNoKen.updateLayoutParams { height += statusBarHeight }
|
binding.mediaBannerNoKen.updateLayoutParams { height += statusBarHeight }
|
||||||
|
@ -445,7 +445,6 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
||||||
ObjectAnimator.ofFloat(binding.mediaCollapseContainer, "translationX", screenWidth)
|
ObjectAnimator.ofFloat(binding.mediaCollapseContainer, "translationX", screenWidth)
|
||||||
.setDuration(duration).start()
|
.setDuration(duration).start()
|
||||||
binding.mediaBanner.pause()
|
binding.mediaBanner.pause()
|
||||||
if (!uiSettings.immersiveMode) this.window.statusBarColor = color
|
|
||||||
}
|
}
|
||||||
if (percentage <= percent && isCollapsed) {
|
if (percentage <= percent && isCollapsed) {
|
||||||
isCollapsed = false
|
isCollapsed = false
|
||||||
|
@ -458,7 +457,6 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
|
||||||
ObjectAnimator.ofFloat(binding.mediaCollapseContainer, "translationX", 0f)
|
ObjectAnimator.ofFloat(binding.mediaCollapseContainer, "translationX", 0f)
|
||||||
.setDuration(duration).start()
|
.setDuration(duration).start()
|
||||||
if (uiSettings.bannerAnimations) binding.mediaBanner.resume()
|
if (uiSettings.bannerAnimations) binding.mediaBanner.resume()
|
||||||
if (!uiSettings.immersiveMode) this.window.statusBarColor = color
|
|
||||||
}
|
}
|
||||||
if (percentage == 1 && model.scrolledToTop.value != false) model.scrolledToTop.postValue(
|
if (percentage == 1 && model.scrolledToTop.value != false) model.scrolledToTop.postValue(
|
||||||
false
|
false
|
||||||
|
|
|
@ -279,7 +279,7 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
||||||
if (video != null) {
|
if (video != null) {
|
||||||
Helper.startAnimeDownloadService(
|
Helper.startAnimeDownloadService(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
media!!.userPreferredName,
|
media!!.nameMAL ?: media!!.nameRomaji,
|
||||||
episode.number,
|
episode.number,
|
||||||
video,
|
video,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -56,7 +56,7 @@ abstract class BaseParser {
|
||||||
* **/
|
* **/
|
||||||
open suspend fun autoSearch(mediaObj: Media): ShowResponse? {
|
open suspend fun autoSearch(mediaObj: Media): ShowResponse? {
|
||||||
var response: ShowResponse? = loadSavedShowResponse(mediaObj.id)
|
var response: ShowResponse? = loadSavedShowResponse(mediaObj.id)
|
||||||
if (response != null && this !is OfflineMangaParser) {
|
if (response != null && this !is OfflineMangaParser && this !is OfflineAnimeParser) {
|
||||||
saveShowResponse(mediaObj.id, response, true)
|
saveShowResponse(mediaObj.id, response, true)
|
||||||
} else {
|
} else {
|
||||||
setUserText("Searching : ${mediaObj.mainName()}")
|
setUserText("Searching : ${mediaObj.mainName()}")
|
||||||
|
|
|
@ -13,14 +13,15 @@ import ani.dantotsu.MainActivity
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.databinding.BottomSheetSettingsBinding
|
import ani.dantotsu.databinding.BottomSheetSettingsBinding
|
||||||
|
import ani.dantotsu.download.anime.OfflineAnimeFragment
|
||||||
import ani.dantotsu.download.manga.OfflineMangaFragment
|
import ani.dantotsu.download.manga.OfflineMangaFragment
|
||||||
import ani.dantotsu.home.AnimeFragment
|
import ani.dantotsu.home.AnimeFragment
|
||||||
import ani.dantotsu.home.HomeFragment
|
import ani.dantotsu.home.HomeFragment
|
||||||
import ani.dantotsu.home.LoginFragment
|
import ani.dantotsu.home.LoginFragment
|
||||||
import ani.dantotsu.home.MangaFragment
|
import ani.dantotsu.home.MangaFragment
|
||||||
import ani.dantotsu.home.NoInternet
|
import ani.dantotsu.home.NoInternet
|
||||||
import ani.dantotsu.loadImage
|
|
||||||
import ani.dantotsu.incognitoNotification
|
import ani.dantotsu.incognitoNotification
|
||||||
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.offline.OfflineFragment
|
import ani.dantotsu.offline.OfflineFragment
|
||||||
import ani.dantotsu.openLinkInBrowser
|
import ani.dantotsu.openLinkInBrowser
|
||||||
import ani.dantotsu.others.imagesearch.ImageSearchActivity
|
import ani.dantotsu.others.imagesearch.ImageSearchActivity
|
||||||
|
@ -145,7 +146,10 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
PageType.ANIME -> {
|
PageType.ANIME -> {
|
||||||
val intent = Intent(activity, NoInternet::class.java)
|
val intent = Intent(activity, NoInternet::class.java)
|
||||||
intent.putExtra("FRAGMENT_CLASS_NAME", OfflineFragment::class.java.name)
|
intent.putExtra(
|
||||||
|
"FRAGMENT_CLASS_NAME",
|
||||||
|
OfflineAnimeFragment::class.java.name
|
||||||
|
)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,15 @@ import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.Window
|
||||||
|
import android.view.WindowManager
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
import com.google.android.material.color.DynamicColorsOptions
|
import com.google.android.material.color.DynamicColorsOptions
|
||||||
|
|
||||||
|
|
||||||
class ThemeManager(private val context: Context) {
|
class ThemeManager(private val context: Activity) {
|
||||||
fun applyTheme(fromImage: Bitmap? = null) {
|
fun applyTheme(fromImage: Bitmap? = null) {
|
||||||
val useOLED = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
val useOLED = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||||
.getBoolean("use_oled", false) && isDarkThemeActive(context)
|
.getBoolean("use_oled", false) && isDarkThemeActive(context)
|
||||||
|
@ -54,9 +57,24 @@ class ThemeManager(private val context: Context) {
|
||||||
else -> if (useOLED) R.style.Theme_Dantotsu_PurpleOLED else R.style.Theme_Dantotsu_Purple
|
else -> if (useOLED) R.style.Theme_Dantotsu_PurpleOLED else R.style.Theme_Dantotsu_Purple
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val window = context.window
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||||
|
window.statusBarColor = 0x00000000
|
||||||
context.setTheme(themeToApply)
|
context.setTheme(themeToApply)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setWindowFlag(activity: Activity, bits: Int, on: Boolean) {
|
||||||
|
val win: Window = activity.window
|
||||||
|
val winParams: WindowManager.LayoutParams = win.attributes
|
||||||
|
if (on) {
|
||||||
|
winParams.flags = winParams.flags or bits
|
||||||
|
} else {
|
||||||
|
winParams.flags = winParams.flags and bits.inv()
|
||||||
|
}
|
||||||
|
win.setAttributes(winParams)
|
||||||
|
}
|
||||||
|
|
||||||
private fun applyDynamicColors(
|
private fun applyDynamicColors(
|
||||||
useMaterialYou: Boolean,
|
useMaterialYou: Boolean,
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
tools:context=".home.MangaFragment">
|
tools:context=".home.MangaFragment">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:id="@+id/mangaRefresh"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
|
@ -16,6 +17,8 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<color name="nav_bg_inv">#001C1C1C</color>
|
<color name="nav_bg_inv">#001C1C1C</color>
|
||||||
<color name="nav_tab">#40ffffff</color>
|
<color name="nav_tab">#40ffffff</color>
|
||||||
<color name="nav_tab_disabled">#40ffffff</color>
|
<color name="nav_tab_disabled">#40ffffff</color>
|
||||||
<color name="status">#54000000</color>
|
<color name="status">#00000000</color>
|
||||||
<color name="nav_status">#80000000</color>
|
<color name="nav_status">#80000000</color>
|
||||||
<color name="filler">#29FF6B08</color>
|
<color name="filler">#29FF6B08</color>
|
||||||
<color name="chip">#b3aead</color>
|
<color name="chip">#b3aead</color>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<color name="nav_bg_inv">#00FFFFFF</color>
|
<color name="nav_bg_inv">#00FFFFFF</color>
|
||||||
<color name="nav_tab">#40000000</color>
|
<color name="nav_tab">#40000000</color>
|
||||||
<color name="nav_tab_disabled">#19000000</color>
|
<color name="nav_tab_disabled">#19000000</color>
|
||||||
<color name="status">#54EEEEEE</color>
|
<color name="status">#00000000</color>
|
||||||
<color name="button_icon">#A9FFFFFF</color>
|
<color name="button_icon">#A9FFFFFF</color>
|
||||||
<color name="nav_status">#80FFFFFF</color>
|
<color name="nav_status">#80FFFFFF</color>
|
||||||
<color name="fav">#ad5edd</color>
|
<color name="fav">#ad5edd</color>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
<item name="android:navigationBarColor">?android:colorBackground</item>
|
<item name="android:navigationBarColor">?android:colorBackground</item>
|
||||||
<item name="android:windowTranslucentStatus">true</item>
|
<item name="android:windowTranslucentStatus">true</item>
|
||||||
|
<item name="android:windowContentOverlay">@null</item>
|
||||||
<item name="elevationOverlayEnabled">false</item>
|
<item name="elevationOverlayEnabled">false</item>
|
||||||
<item name="windowActionBar">false</item>
|
<item name="windowActionBar">false</item>
|
||||||
<item name="windowNoTitle">true</item>
|
<item name="windowNoTitle">true</item>
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Dantotsu" parent="Theme.Base">
|
<style name="Theme.Dantotsu" parent="Theme.Base">
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
<item name="android:windowLightStatusBar">false</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Dantotsu.NoActionBar">
|
<style name="Theme.Dantotsu.NoActionBar">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue