Merge pull request #54 from rebelonion/dev

Dev
This commit is contained in:
rebelonion 2023-11-21 02:52:46 -06:00 committed by GitHub
commit 533aa9f56e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 262 additions and 75 deletions

View file

@ -1,16 +1,19 @@
package ani.dantotsu.download.manga package ani.dantotsu.download.manga
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.OvershootInterpolator import android.view.animation.OvershootInterpolator
import android.widget.GridView import android.widget.GridView
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import androidx.core.view.updatePaddingRelative import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -24,9 +27,15 @@ import ani.dantotsu.download.DownloadsManager
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.media.manga.MangaNameAdapter
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.px import ani.dantotsu.px
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.statusBarHeight 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.firebase.crashlytics.FirebaseCrashlytics
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -46,6 +55,28 @@ class OfflineMangaFragment: Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_manga_offline, container, false) val view = inflater.inflate(R.layout.fragment_manga_offline, container, false)
val textInputLayout = view.findViewById<TextInputLayout>(R.id.offlineMangaSearchBar)
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 animeUserAvatar= view.findViewById<ShapeableImageView>(R.id.offlineMangaUserAvatar)
animeUserAvatar.setSafeOnClickListener {
SettingsDialogFragment(SettingsDialogFragment.Companion.PageType.HOME).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())
}
gridView = view.findViewById(R.id.gridView) gridView = view.findViewById(R.id.gridView)
getDownloads() getDownloads()
adapter = OfflineMangaAdapter(requireContext(), downloads) adapter = OfflineMangaAdapter(requireContext(), downloads)
@ -81,13 +112,6 @@ class OfflineMangaFragment: Fragment() {
} }
} }
} }
val refreshLayout = view.findViewById<SwipeRefreshLayout>(R.id.mangaRefresh)
refreshLayout.setSlingshotDistance(height + 128)
refreshLayout.setProgressViewEndTarget(false, height + 128)
refreshLayout.setOnRefreshListener {
Refresh.activity[this.hashCode()]!!.postValue(true)
}
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() {

View file

@ -14,4 +14,5 @@ data class Selected(
var server: String? = null, var server: String? = null,
var video: Int = 0, var video: Int = 0,
var latest: Float = 0f, var latest: Float = 0f,
var scanlators: List<String>? = null,
) : Serializable ) : Serializable

View file

@ -12,9 +12,10 @@ data class MangaChapter(
var title: String? = null, var title: String? = null,
var description: String? = null, var description: String? = null,
var sChapter: SChapter, var sChapter: SChapter,
var progress: String? = null, val scanlator: String? = null,
var progress: String? = ""
) : Serializable { ) : Serializable {
constructor(chapter: MangaChapter) : this(chapter.number, chapter.link, chapter.title, chapter.description, chapter.sChapter) constructor(chapter: MangaChapter) : this(chapter.number, chapter.link, chapter.title, chapter.description, chapter.sChapter, chapter.scanlator)
private val images = mutableListOf<MangaImage>() private val images = mutableListOf<MangaImage>()
fun images(): List<MangaImage> = images fun images(): List<MangaImage> = images

View file

@ -76,6 +76,7 @@ class MangaChapterAdapter(
// Find the position of the chapter and notify only that item // Find the position of the chapter and notify only that item
val position = arr.indexOfFirst { it.number == chapterNumber } val position = arr.indexOfFirst { it.number == chapterNumber }
if (position != -1) { if (position != -1) {
arr[position].progress = "Downloaded"
notifyItemChanged(position) notifyItemChanged(position)
} }
} }
@ -113,8 +114,10 @@ class MangaChapterAdapter(
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun bind(chapterNumber: String, progress: String?) { fun bind(chapterNumber: String, progress: String?) {
if (progress != null) { if (progress != null) {
binding.itemChapterTitle.text = "Downloading: ${progress}%" binding.itemChapterTitle.visibility = View.VISIBLE
binding.itemChapterTitle.text = "$progress"
}else{ }else{
binding.itemChapterTitle.visibility = View.GONE
binding.itemChapterTitle.text = "" binding.itemChapterTitle.text = ""
} }
if (activeDownloads.contains(chapterNumber)) { if (activeDownloads.contains(chapterNumber)) {
@ -186,16 +189,9 @@ class MangaChapterAdapter(
holder.bind(ep.number, ep.progress) holder.bind(ep.number, ep.progress)
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings) setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
binding.itemChapterNumber.text = ep.number binding.itemChapterNumber.text = ep.number
/*if (!ep.progress.isNullOrEmpty()) { if (ep.progress.isNullOrEmpty()) {
binding.itemChapterTitle.text = ep.progress binding.itemChapterTitle.visibility = View.GONE
binding.itemChapterTitle.setOnLongClickListener { } else binding.itemChapterTitle.visibility = View.VISIBLE
binding.itemChapterTitle.maxLines.apply {
binding.itemChapterTitle.maxLines = if (this == 1) 3 else 1
}
true
}
binding.itemChapterTitle.visibility = View.VISIBLE
} else*/ binding.itemChapterTitle.visibility = View.VISIBLE
if (media.userProgress != null) { if (media.userProgress != null) {
if ((MangaNameAdapter.findChapterNumber(ep.number) if ((MangaNameAdapter.findChapterNumber(ep.number)
@ -227,4 +223,4 @@ class MangaChapterAdapter(
} }
} }

View file

@ -1,16 +1,19 @@
package ani.dantotsu.media.manga package ani.dantotsu.media.manga
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.* import ani.dantotsu.*
import ani.dantotsu.App.Companion.context
import ani.dantotsu.media.anime.handleProgress import ani.dantotsu.media.anime.handleProgress
import ani.dantotsu.databinding.ItemAnimeWatchBinding import ani.dantotsu.databinding.ItemAnimeWatchBinding
import ani.dantotsu.databinding.ItemChipBinding import ani.dantotsu.databinding.ItemChipBinding
@ -37,6 +40,9 @@ class MangaReadAdapter(
var subscribe: MediaDetailsActivity.PopImageButton? = null var subscribe: MediaDetailsActivity.PopImageButton? = null
private var _binding: ItemAnimeWatchBinding? = null private var _binding: ItemAnimeWatchBinding? = null
val hiddenScanlators = mutableListOf<String>()
var scanlatorSelectionListener: ScanlatorSelectionListener? = null
var options = listOf<String>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val bind = ItemAnimeWatchBinding.inflate(LayoutInflater.from(parent.context), parent, false) val bind = ItemAnimeWatchBinding.inflate(LayoutInflater.from(parent.context), parent, false)
@ -131,6 +137,46 @@ class MangaReadAdapter(
binding.animeSourceTop.rotation = if (reversed) -90f else 90f binding.animeSourceTop.rotation = if (reversed) -90f else 90f
fragment.onIconPressed(style, reversed) fragment.onIconPressed(style, reversed)
} }
binding.animeScanlatorTop.setOnClickListener {
val dialogView = LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
val checkboxContainer = dialogView.findViewById<LinearLayout>(R.id.checkboxContainer)
// Dynamically add checkboxes
options.forEach { option ->
val checkBox = CheckBox(currContext()).apply {
text = option
}
//set checked if it's already selected
if(media.selected!!.scanlators != null){
checkBox.isChecked = media.selected!!.scanlators?.contains(option) != true
scanlatorSelectionListener?.onScanlatorsSelected()
}else{
checkBox.isChecked = true
}
checkboxContainer.addView(checkBox)
}
// Create AlertDialog
AlertDialog.Builder(currContext())
.setView(dialogView)
.setPositiveButton("OK") { dialog, which ->
//add unchecked to hidden
hiddenScanlators.clear()
for (i in 0 until checkboxContainer.childCount) {
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
if (!checkBox.isChecked) {
hiddenScanlators.add(checkBox.text.toString())
}
}
media.selected!!.scanlators = hiddenScanlators
scanlatorSelectionListener?.onScanlatorsSelected()
}
.setNegativeButton("Cancel", null)
.show()
}
var selected = when (style) { var selected = when (style) {
0 -> binding.animeSourceList 0 -> binding.animeSourceList
1 -> binding.animeSourceCompact 1 -> binding.animeSourceCompact
@ -201,6 +247,7 @@ class MangaReadAdapter(
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun handleChapters() { fun handleChapters() {
val binding = _binding val binding = _binding
if (binding != null) { if (binding != null) {
if (media.manga?.chapters != null) { if (media.manga?.chapters != null) {
@ -208,7 +255,11 @@ class MangaReadAdapter(
val anilistEp = (media.userProgress ?: 0).plus(1) val anilistEp = (media.userProgress ?: 0).plus(1)
val appEp = loadData<String>("${media.id}_current_chp")?.toIntOrNull() ?: 1 val appEp = loadData<String>("${media.id}_current_chp")?.toIntOrNull() ?: 1
var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString() var continueEp = (if (anilistEp > appEp) anilistEp else appEp).toString()
val formattedChapters = chapters.map { MangaNameAdapter.findChapterNumber(it)?.toInt()?.toString() } val filteredChapters = chapters.filter { chapterKey ->
val chapter = media.manga.chapters!![chapterKey]!!
chapter.scanlator !in hiddenScanlators
}
val formattedChapters = filteredChapters.map { MangaNameAdapter.findChapterNumber(it)?.toInt()?.toString() }
if (formattedChapters.contains(continueEp)) { if (formattedChapters.contains(continueEp)) {
continueEp = chapters[formattedChapters.indexOf(continueEp)] continueEp = chapters[formattedChapters.indexOf(continueEp)]
binding.animeSourceContinue.visibility = View.VISIBLE binding.animeSourceContinue.visibility = View.VISIBLE
@ -278,4 +329,8 @@ class MangaReadAdapter(
override fun getItemCount(): Int = 1 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 {
fun onScanlatorsSelected()
}

View file

@ -67,7 +67,7 @@ import kotlin.math.roundToInt
import android.Manifest import android.Manifest
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
open class MangaReadFragment : Fragment() { open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
private var _binding: FragmentAnimeWatchBinding? = null private var _binding: FragmentAnimeWatchBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private val model: MediaDetailsViewModel by activityViewModels() private val model: MediaDetailsViewModel by activityViewModels()
@ -160,6 +160,7 @@ open class MangaReadFragment : Fragment() {
model.mangaReadSources = if (media.isAdult) HMangaSources else MangaSources model.mangaReadSources = if (media.isAdult) HMangaSources else MangaSources
headerAdapter = MangaReadAdapter(it, this, model.mangaReadSources!!) 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){
@ -182,45 +183,70 @@ open class MangaReadFragment : Fragment() {
} }
} }
model.getMangaChapters().observe(viewLifecycleOwner) { loadedChapters -> model.getMangaChapters().observe(viewLifecycleOwner) { _ ->
if (loadedChapters != null) { updateChapters()
val chapters = loadedChapters[media.selected!!.sourceIndex] }
if (chapters != null) { }
media.manga?.chapters = chapters
//CHIP GROUP override fun onScanlatorsSelected() {
val total = chapters.size updateChapters()
val divisions = total.toDouble() / 10 }
start = 0
end = null
val limit = when {
(divisions < 25) -> 25
(divisions < 50) -> 50
else -> 100
}
headerAdapter.clearChips()
if (total > limit) {
val arr = chapters.keys.toTypedArray()
val stored = ceil((total).toDouble() / limit).toInt()
val position = clamp(media.selected!!.chip, 0, stored - 1)
val last = if (position + 1 == stored) total else (limit * (position + 1))
start = limit * (position)
end = last - 1
headerAdapter.updateChips(
limit,
arr,
(1..stored).toList().toTypedArray(),
position
)
}
headerAdapter.subscribeButton(true) private fun updateChapters() {
reload() val loadedChapters = model.getMangaChapters().value
if (loadedChapters != null) {
val chapters = loadedChapters[media.selected!!.sourceIndex]
if (chapters != null) {
headerAdapter.options = getScanlators(chapters)
val filteredChapters = chapters.filterNot { (_, chapter) ->
chapter.scanlator in headerAdapter.hiddenScanlators
} }
media.manga?.chapters = filteredChapters.toMutableMap()
//CHIP GROUP
val total = filteredChapters.size
val divisions = total.toDouble() / 10
start = 0
end = null
val limit = when {
(divisions < 25) -> 25
(divisions < 50) -> 50
else -> 100
}
headerAdapter.clearChips()
if (total > limit) {
val arr = filteredChapters.keys.toTypedArray()
val stored = ceil((total).toDouble() / limit).toInt()
val position = clamp(media.selected!!.chip, 0, stored - 1)
val last = if (position + 1 == stored) total else (limit * (position + 1))
start = limit * (position)
end = last - 1
headerAdapter.updateChips(
limit,
arr,
(1..stored).toList().toTypedArray(),
position
)
}
headerAdapter.subscribeButton(true)
reload()
} }
} }
} }
fun getScanlators(chap: MutableMap<String, MangaChapter>?): List<String> {
val scanlators = mutableListOf<String>()
if (chap != null) {
val chapters = chap.values
for (chapter in chapters) {
scanlators.add(chapter.scanlator ?: "Unknown")
}
}
return scanlators.distinct()
}
fun onSourceChange(i: Int): MangaParser { fun onSourceChange(i: Int): MangaParser {
media.manga?.chapters = null media.manga?.chapters = null
reload() reload()
@ -453,7 +479,7 @@ open class MangaReadFragment : Fragment() {
ACTION_DOWNLOAD_PROGRESS -> { ACTION_DOWNLOAD_PROGRESS -> {
val chapterNumber = intent.getStringExtra(EXTRA_CHAPTER_NUMBER) val chapterNumber = intent.getStringExtra(EXTRA_CHAPTER_NUMBER)
val progress = intent.getIntExtra("progress", 0) val progress = intent.getIntExtra("progress", 0)
//chapterNumber?.let { chapterAdapter.updateDownloadProgress(it, progress) } chapterNumber?.let { chapterAdapter.updateDownloadProgress(it, progress)
} }
} }
} }

View file

@ -532,8 +532,9 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
return MangaChapter( return MangaChapter(
sChapter.name, sChapter.name,
sChapter.url, sChapter.url,
"", sChapter.name,
null, null,
sChapter.scanlator,
sChapter sChapter
) )
} }

View file

@ -67,7 +67,7 @@ data class MangaChapter(
//Self-Descriptive //Self-Descriptive
val title: String? = null, val title: String? = null,
val description: String? = null, val description: String? = null,
val scanlator: String? = null,
val sChapter: SChapter, val sChapter: SChapter,
) )

View file

@ -3,6 +3,7 @@ package ani.dantotsu.parsers
import android.os.Environment import android.os.Environment
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.media.manga.MangaNameAdapter
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import me.xdrop.fuzzywuzzy.FuzzySearch import me.xdrop.fuzzywuzzy.FuzzySearch
@ -30,10 +31,11 @@ class OfflineMangaParser: MangaParser() {
if (directory.exists()) { if (directory.exists()) {
directory.listFiles()?.forEach { directory.listFiles()?.forEach {
if (it.isDirectory) { if (it.isDirectory) {
val chapter = MangaChapter(it.name, "$mangaLink/${it.name}", it.name, null, SChapter.create()) val chapter = MangaChapter(it.name, "$mangaLink/${it.name}", it.name, null, null, SChapter.create())
chapters.add(chapter) chapters.add(chapter)
} }
} }
chapters.sortBy { MangaNameAdapter.findChapterNumber(it.number) }
return chapters return chapters
} }
return emptyList() return emptyList()

View file

@ -170,7 +170,7 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
binding.skipExtensionIcons.setOnCheckedChangeListener { _, isChecked -> binding.skipExtensionIcons.setOnCheckedChangeListener { _, isChecked ->
saveData("skip_extension_icons", isChecked) saveData("skip_extension_icons", isChecked)
} }
binding.NSFWExtension.isChecked = loadData("NFSWExtension") ?: false binding.NSFWExtension.isChecked = loadData("NFSWExtension") ?: true
binding.NSFWExtension.setOnCheckedChangeListener { _, isChecked -> binding.NSFWExtension.setOnCheckedChangeListener { _, isChecked ->
saveData("NFSWExtension", isChecked) saveData("NFSWExtension", isChecked)

View file

@ -78,7 +78,7 @@ class AnimeExtensionPagingSource(
val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet() val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet()
val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions } val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions }
val query = searchQuery.first() val query = searchQuery.first()
var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: true
val filteredExtensions = if (query.isEmpty()) { val filteredExtensions = if (query.isEmpty()) {
availableExtensions availableExtensions
} else { } else {

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container" android:id="@+id/fragment_container"
android:paddingTop="32dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />

View file

@ -20,6 +20,7 @@
<FrameLayout <FrameLayout
android:id="@+id/fragmentContainer" android:id="@+id/fragmentContainer"
android:paddingTop="32dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
</FrameLayout> </FrameLayout>

View file

@ -0,0 +1,19 @@
<!-- custom_dialog_layout.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/checkboxContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</ScrollView>
</LinearLayout>

View file

@ -6,8 +6,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".home.MangaFragment"> tools:context=".home.MangaFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout <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"
@ -19,17 +18,67 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<TextView <LinearLayout
android:id="@+id/mangaOfflineTitle" android:id="@+id/animeTitleContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="16dp" android:layout_margin="32dp"
android:text="Offline Manga" android:orientation="horizontal">
android:textColor="?attr/colorOnSurface"
android:textSize="24sp" <com.google.android.material.textfield.TextInputLayout
android:textStyle="bold" android:id="@+id/offlineMangaSearchBar"
android:fontFamily="@font/poppins" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:gravity="center_horizontal" /> android:layout_width="0dp"
android:layout_height="56dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:hint="@string/manga"
android:textColorHint="@color/bg_opp"
android:transitionName="@string/search"
app:boxBackgroundColor="?attr/colorPrimaryContainer"
app:boxCornerRadiusBottomEnd="28dp"
app:boxCornerRadiusBottomStart="28dp"
app:boxCornerRadiusTopEnd="28dp"
app:boxCornerRadiusTopStart="28dp"
app:endIconDrawable="@drawable/ic_round_search_24"
app:endIconTint="@color/bg_opp"
app:boxStrokeColor="@color/text_input_layout_stroke_color"
app:hintAnimationEnabled="true">
<AutoCompleteTextView
android:id="@+id/animeSearchBarText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:focusable="false"
android:fontFamily="@font/poppins_bold"
android:inputType="none"
android:padding="8dp"
android:textSize="14sp"
tools:ignore="LabelFor,TextContrastCheck" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.card.MaterialCardView
android:id="@+id/offlineMangaAvatarContainer"
android:layout_width="52dp"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
app:cardBackgroundColor="?attr/colorPrimaryContainer"
app:strokeColor="@color/text_input_layout_stroke_color"
app:cardCornerRadius="26dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/offlineMangaUserAvatar"
android:layout_width="52dp"
android:layout_height="52dp"
android:scaleType="center"
android:tint="@color/bg_opp"
app:srcCompat="@drawable/ic_round_settings_24"
tools:ignore="ContentDescription,ImageContrastCheck" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- This TextView might overlap with GridView if GridView has items --> <!-- This TextView might overlap with GridView if GridView has items -->
<TextView <TextView
@ -54,7 +103,7 @@
android:padding="10dp" android:padding="10dp"
android:gravity="center" /> android:gravity="center" />
</LinearLayout> </LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </FrameLayout>
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:id="@+id/mangaPageScrollTop" android:id="@+id/mangaPageScrollTop"

View file

@ -245,6 +245,16 @@
app:tint="?attr/colorOnBackground" app:tint="?attr/colorOnBackground"
tools:ignore="ContentDescription,ImageContrastCheck" /> tools:ignore="ContentDescription,ImageContrastCheck" />
<ImageView
android:id="@+id/animeScanlatorTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="1"
android:padding="8dp"
app:srcCompat="@drawable/ic_round_edit_note_24"
app:tint="?attr/colorOnBackground"
tools:ignore="ContentDescription,ImageContrastCheck" />
<ImageView <ImageView
android:id="@+id/animeSourceTop" android:id="@+id/animeSourceTop"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -52,6 +52,7 @@
android:singleLine="true" android:singleLine="true"
android:textSize="14dp" android:textSize="14dp"
tools:ignore="SpUsage" tools:ignore="SpUsage"
android:paddingEnd="8dp"
tools:text="1" /> tools:text="1" />
</LinearLayout> </LinearLayout>
@ -91,7 +92,7 @@
android:id="@+id/itemEpisodeViewed" android:id="@+id/itemEpisodeViewed"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end" android:layout_gravity="start"
android:layout_margin="8dp" android:layout_margin="8dp"
android:visibility="gone" android:visibility="gone"
app:srcCompat="@drawable/ic_round_remove_red_eye_24" app:srcCompat="@drawable/ic_round_remove_red_eye_24"