Compare commits

...

5 Commits

Author SHA1 Message Date
Finnley Somdahl
9c0ef7a788 bugfixes and themes 2023-10-27 00:47:44 -05:00
Finnley Somdahl
960c2b4113 Update stable.md 2023-10-26 02:11:43 -05:00
Finnley Somdahl
1eb85d4419 new themes 2023-10-26 02:08:35 -05:00
Finnley Somdahl
20bea76e6c subtitle, image, and extension page fixes 2023-10-26 00:40:57 -05:00
Finnley Somdahl
866bd3b3a9 theme cleanup 2023-10-25 15:55:29 -05:00
74 changed files with 1939 additions and 1060 deletions

View File

@@ -1,6 +1,4 @@
# **Dantotsu** (🚧 ALPHA 🚧)
> ⚠️ **WARNING**: This project is in alpha stage. Things may not work as expected.
# **Dantotsu**
<p align="center">
<a href="https://discord.gg/4HPZ5nAWwM"><img src="https://img.shields.io/badge/Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white"></a>
@@ -26,14 +24,14 @@ Dantotsu is crafted from the ashes of Saikou and based on simplistic yet state-o
| Type | Status |
| ---------------- | ------- |
| Anime Extensions | Working |
| Manga Extensions | "Working" |
| Manga Extensions | Working |
| Light Novel Extensions | Not Working |
## APP FEATURES
- Easy and functional way to both, watch anime and read manga, ad-free.
- Easy and functional way to both, watch anime and read manga.
- A completely open source app with a nice UI & Animations :)
@@ -59,14 +57,16 @@ add your own extensions in the settings menu (Dantotsu has no affiliation with a
## Planned Stuff
- get app out of alpha
- TV Support
- Accent Color Change (RIP Hot Pink Supremacy.)
- LN Support
- Offline Viewing
## Rejected Stuff (still rejected)
- Sources of any language except English
- Official support of any language except English
- News Section in the App

View File

@@ -21,7 +21,7 @@ android {
minSdk 23
targetSdk 34
versionCode ((System.currentTimeMillis() / 60000).toInteger())
versionName "0.1.3"
versionName "1.0.0"
signingConfig signingConfigs.debug
}
@@ -96,6 +96,7 @@ dependencies {
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
implementation 'com.alexvasilkov:gesture-views:2.8.3'
implementation 'com.github.VipulOG:ebook-reader:0.1.6'
implementation 'androidx.paging:paging-runtime-ktx:3.2.1'
// string matching
implementation 'me.xdrop:fuzzywuzzy:1.4.0'

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Dantotsu α</string>
<string name="app_name">Dantotsu</string>
</resources>

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -188,6 +188,9 @@ fun Activity.hideStatusBar() {
open class BottomSheetDialogFragment : BottomSheetDialogFragment() {
override fun onStart() {
super.onStart()
val window = dialog?.window
val decorView: View = window?.decorView ?: return
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
if (this.resources.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) {
val behavior = BottomSheetBehavior.from(requireView().parent as View)
behavior.state = BottomSheetBehavior.STATE_EXPANDED

View File

@@ -7,7 +7,10 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -21,6 +24,7 @@ import android.view.animation.AnticipateInterpolator
import android.widget.TextView
import androidx.activity.addCallback
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.animation.doOnEnd
import androidx.core.app.ActivityCompat
@@ -60,6 +64,8 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import nl.joery.animatedbottombar.AnimatedBottomBar
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.Serializable
@@ -70,9 +76,8 @@ class MainActivity : AppCompatActivity() {
private var load = false
private var uiSettings = UserInterfaceSettings()
private val animeExtensionManager: AnimeExtensionManager by injectLazy()
private val mangaExtensionManager: MangaExtensionManager by injectLazy()
private val animeExtensionManager: AnimeExtensionManager = Injekt.get()
private val mangaExtensionManager: MangaExtensionManager = Injekt.get()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
@@ -80,6 +85,17 @@ class MainActivity : AppCompatActivity() {
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val bottomBar = findViewById<AnimatedBottomBar>(R.id.navbar)
val backgroundDrawable = bottomBar.background as GradientDrawable
val currentColor = backgroundDrawable.color?.defaultColor ?: 0
val semiTransparentColor = (currentColor and 0x00FFFFFF) or 0xE8000000.toInt()
backgroundDrawable.setColor(semiTransparentColor)
bottomBar.background = backgroundDrawable
}
val animeScope = CoroutineScope(Dispatchers.Default)
animeScope.launch {
animeExtensionManager.findAvailableExtensions()
@@ -109,24 +125,40 @@ class MainActivity : AppCompatActivity() {
binding.root.isMotionEventSplittingEnabled = false
lifecycleScope.launch {
val splash = SplashScreenBinding.inflate(layoutInflater)
binding.root.addView(splash.root)
(splash.splashImage.drawable as Animatable).start()
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
val splash = SplashScreenBinding.inflate(layoutInflater)
binding.root.addView(splash.root)
(splash.splashImage.drawable as Animatable).start()
// Wait for 2 seconds (2000 milliseconds)
delay(2000)
delay(1200)
// Now perform the animation
ObjectAnimator.ofFloat(
splash.root,
View.TRANSLATION_Y,
0f,
-splash.root.height.toFloat()
).apply {
interpolator = AnticipateInterpolator()
duration = 200L
doOnEnd { binding.root.removeView(splash.root) }
start()
ObjectAnimator.ofFloat(
splash.root,
View.TRANSLATION_Y,
0f,
-splash.root.height.toFloat()
).apply {
interpolator = AnticipateInterpolator()
duration = 200L
doOnEnd { binding.root.removeView(splash.root) }
start()
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
splashScreen.setOnExitAnimationListener { splashScreenView ->
ObjectAnimator.ofFloat(
splashScreenView,
View.TRANSLATION_Y,
0f,
-splashScreenView.height.toFloat()
).apply {
interpolator = AnticipateInterpolator()
duration = 200L
doOnEnd { splashScreenView.remove() }
start()
}
}
}
@@ -238,13 +270,6 @@ class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
if (ActivityHelper.shouldRefreshMainActivity) {
ActivityHelper.shouldRefreshMainActivity = false
Refresh.all()
finish()
startActivity(Intent(this, MainActivity::class.java))
initActivity(this)
}
}
@@ -264,8 +289,4 @@ class MainActivity : AppCompatActivity() {
}
}
}
object ActivityHelper {
var shouldRefreshMainActivity: Boolean = false
}
}

View File

@@ -16,7 +16,7 @@ fun updateProgress(media: Media, number: String) {
if (Anilist.userid != null) {
CoroutineScope(Dispatchers.IO).launch {
val a = number.toFloatOrNull()?.roundToInt()
if (a != media.userProgress) {
if ((a?:0) > (media.userProgress?:0)) {
Anilist.mutation.editList(
media.id,
a,

View File

@@ -17,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.media.GenreActivity
import ani.dantotsu.MediaPageTransformer
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.databinding.ItemAnimePageBinding
import ani.dantotsu.loadData
@@ -31,6 +32,8 @@ import ani.dantotsu.setSlideUp
import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.statusBarHeight
import com.google.android.material.card.MaterialCardView
import com.google.android.material.textfield.TextInputLayout
class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHolder>() {
val ready = MutableLiveData(false)
@@ -49,6 +52,13 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
binding = holder.binding
trendingViewPager = binding.animeTrendingViewPager
val textInputLayout = holder.itemView.findViewById<TextInputLayout>(R.id.animeSearchBar)
val currentColor = textInputLayout.boxBackgroundColor
val semiTransparentColor = (currentColor and 0x00FFFFFF) or 0xA8000000.toInt()
textInputLayout.boxBackgroundColor = semiTransparentColor
val materialCardView = holder.itemView.findViewById<MaterialCardView>(R.id.animeUserAvatarContainer)
materialCardView.setCardBackgroundColor(semiTransparentColor)
binding.animeTitleContainer.updatePadding(top = statusBarHeight)
if (uiSettings.smallView) binding.animeTrendingContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {

View File

@@ -31,6 +31,8 @@ import ani.dantotsu.setSlideUp
import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.statusBarHeight
import com.google.android.material.card.MaterialCardView
import com.google.android.material.textfield.TextInputLayout
class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHolder>() {
val ready = MutableLiveData(false)
@@ -49,6 +51,13 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
binding = holder.binding
trendingViewPager = binding.mangaTrendingViewPager
val textInputLayout = holder.itemView.findViewById<TextInputLayout>(R.id.mangaSearchBar)
val currentColor = textInputLayout.boxBackgroundColor
val semiTransparentColor= (currentColor and 0x00FFFFFF) or 0xA8000000.toInt()
textInputLayout.boxBackgroundColor = semiTransparentColor
val materialCardView = holder.itemView.findViewById<MaterialCardView>(R.id.mangaUserAvatarContainer)
materialCardView.setCardBackgroundColor(semiTransparentColor)
binding.mangaTitleContainer.updatePadding(top = statusBarHeight)
if (uiSettings.smallView) binding.mangaTrendingContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {

View File

@@ -4,6 +4,8 @@ import android.annotation.SuppressLint
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.view.Window
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
@@ -12,7 +14,9 @@ import androidx.lifecycle.lifecycleScope
import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.databinding.ActivityListBinding
import ani.dantotsu.loadData
import ani.dantotsu.media.user.ListViewPagerAdapter
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.themes.ThemeManager
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
@@ -31,16 +35,16 @@ class CalendarActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivityListBinding.inflate(layoutInflater)
setContentView(binding.root)
val typedValue = TypedValue()
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue, true)
theme.resolveAttribute(com.google.android.material.R.attr.colorOnPrimary, typedValue, true)
val primaryColor = typedValue.data
val typedValue2 = TypedValue()
theme.resolveAttribute(com.google.android.material.R.attr.colorOnPrimary, typedValue2, true)
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue2, true)
val primaryTextColor = typedValue2.data
val typedValue3 = TypedValue()
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimaryContainer, typedValue3, true)
theme.resolveAttribute(com.google.android.material.R.attr.colorSecondary, typedValue3, true)
val secondaryColor = typedValue3.data
window.statusBarColor = primaryColor
@@ -48,8 +52,21 @@ class CalendarActivity : AppCompatActivity() {
binding.listTabLayout.setBackgroundColor(primaryColor)
binding.listAppBar.setBackgroundColor(primaryColor)
binding.listTitle.setTextColor(primaryTextColor)
binding.listTabLayout.setTabTextColors(primaryTextColor, secondaryColor)
binding.listTabLayout.setTabTextColors(primaryTextColor, primaryTextColor)
binding.listTabLayout.setSelectedTabIndicatorColor(primaryTextColor)
val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
if (!uiSettings.immersiveMode) {
this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg_inv)
binding.root.fitsSystemWindows = true
}else{
binding.root.fitsSystemWindows = false
requestWindowFeature(Window.FEATURE_NO_TITLE)
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
setContentView(binding.root)
binding.listTitle.setText(R.string.release_calendar)
binding.listSort.visibility = View.GONE

View File

@@ -190,7 +190,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
R.drawable.ic_round_favorite_24,
R.drawable.ic_round_favorite_border_24,
R.color.bg_opp,
R.color.violet_400,
R.color.violet_400,//TODO: Change to colorSecondary
media.isFav
) {
media.isFav = it

View File

@@ -10,6 +10,7 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.*
@@ -177,6 +178,7 @@ class AnimeWatchAdapter(
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.setOnClickListener {
selected()

View File

@@ -1205,7 +1205,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
else -> MimeTypes.TEXT_SSA
}
)
.setId("2")
.setId("69")
.build()
}
println("sub: $sub")
@@ -1221,7 +1221,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
else -> MimeTypes.TEXT_UNKNOWN
}
)
.setId("2")
.setId("69")
.build()
}
}
@@ -1302,6 +1302,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
)
.setMaxVideoSize(1, 1)
//.setOverrideForType(
// TrackSelectionOverride(trackSelector, 2))
)
if (playbackPosition != 0L && !changingServer && !settings.alwaysContinue) {
@@ -1352,6 +1353,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
}
playerView.player = exoPlayer
try {
mediaSession = MediaSession.Builder(this, exoPlayer).build()
} catch (e: Exception) {
@@ -1572,6 +1574,27 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
}
override fun onTracksChanged(tracks: Tracks) {
tracks.groups.forEach {
println("Track__: $it")
println("Track__: ${it.length}")
println("Track__: ${it.isSelected}")
println("Track__: ${it.type}")
println("Track__: ${it.mediaTrackGroup.id}")
if (it.type == 3 && it.mediaTrackGroup.id == "1:"){
playerView.player?.trackSelectionParameters =
playerView.player?.trackSelectionParameters?.buildUpon()
?.setOverrideForType(
TrackSelectionOverride(it.mediaTrackGroup, it.length - 1))
?.build()!!
}else if(it.type == 3){
playerView.player?.trackSelectionParameters =
playerView.player?.trackSelectionParameters?.buildUpon()
?.addOverride(
TrackSelectionOverride(it.mediaTrackGroup, listOf()))
?.build()!!
}
}
println("Track: ${tracks.groups.size}")
if (tracks.groups.size <= 2) exoQuality.visibility = View.GONE
else {
exoQuality.visibility = View.VISIBLE

View File

@@ -63,7 +63,8 @@ class MangaChapterAdapter(
val binding = holder.binding
setAnimation(fragment.requireContext(), holder.binding.root, fragment.uiSettings)
val ep = arr[position]
binding.itemEpisodeNumber.text = ep.number
val parsedNumber = MangaNameAdapter.findChapterNumber(ep.number)?.toInt()
binding.itemEpisodeNumber.text = parsedNumber?.toString() ?: ep.number
if (media.userProgress != null) {
if ((MangaNameAdapter.findChapterNumber(ep.number) ?: 9999f) <= media.userProgress!!.toFloat())
binding.itemEpisodeViewedCover.visibility = View.VISIBLE

View File

@@ -7,6 +7,7 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.*
@@ -145,6 +146,7 @@ class MangaReadAdapter(
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.setOnClickListener {
selected()

View File

@@ -156,10 +156,6 @@ abstract class BaseImageAdapter(
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
} else {
println("bitmap from cache")
println(link.url)
println(mangaCache.get(link.url))
println("cache size: ${mangaCache.size()}")
mangaCache.get(link.url)?.let { imageData ->
val bitmap = imageData.fetchAndProcessImage(imageData.page, imageData.source, context = this@loadBitmap)
it.load(bitmap)

View File

@@ -4,6 +4,8 @@ import android.annotation.SuppressLint
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.view.Window
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
@@ -13,6 +15,8 @@ import androidx.lifecycle.lifecycleScope
import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.databinding.ActivityListBinding
import ani.dantotsu.loadData
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.themes.ThemeManager
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
@@ -30,16 +34,15 @@ class ListActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
binding = ActivityListBinding.inflate(layoutInflater)
setContentView(binding.root)
val typedValue = TypedValue()
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue, true)
theme.resolveAttribute(com.google.android.material.R.attr.colorOnPrimary, typedValue, true)
val primaryColor = typedValue.data
val typedValue2 = TypedValue()
theme.resolveAttribute(com.google.android.material.R.attr.colorOnPrimary, typedValue2, true)
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue2, true)
val primaryTextColor = typedValue2.data
val typedValue3 = TypedValue()
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimaryContainer, typedValue3, true)
theme.resolveAttribute(com.google.android.material.R.attr.colorSecondary, typedValue3, true)
val secondaryColor = typedValue3.data
window.statusBarColor = primaryColor
@@ -47,8 +50,20 @@ class ListActivity : AppCompatActivity() {
binding.listTabLayout.setBackgroundColor(primaryColor)
binding.listAppBar.setBackgroundColor(primaryColor)
binding.listTitle.setTextColor(primaryTextColor)
binding.listTabLayout.setTabTextColors(primaryTextColor, secondaryColor)
binding.listTabLayout.setTabTextColors(primaryTextColor, primaryTextColor)
binding.listTabLayout.setSelectedTabIndicatorColor(primaryTextColor)
val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
if (!uiSettings.immersiveMode) {
this.window.statusBarColor =
ContextCompat.getColor(this, R.color.nav_bg_inv)
binding.root.fitsSystemWindows = true
}else{
binding.root.fitsSystemWindows = false
requestWindowFeature(Window.FEATURE_NO_TITLE)
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"

View File

@@ -1,6 +1,8 @@
package ani.dantotsu.others
import android.graphics.Color
import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -46,6 +48,12 @@ open class CustomBottomDialog : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = BottomSheetCustomBinding.inflate(inflater, container, false)
val window = dialog?.window
window?.statusBarColor = Color.TRANSPARENT
val typedValue = TypedValue()
val theme = requireContext().theme
theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValue, true)
window?.navigationBarColor = typedValue.data
return binding.root
}

View File

@@ -11,6 +11,7 @@ import ani.dantotsu.BottomSheetDialogFragment
import ani.dantotsu.FileUrl
import ani.dantotsu.R
import ani.dantotsu.databinding.BottomSheetImageBinding
import ani.dantotsu.media.manga.mangareader.BaseImageAdapter.Companion.loadBitmap
import ani.dantotsu.media.manga.mangareader.BaseImageAdapter.Companion.loadBitmap_old
import ani.dantotsu.media.manga.mangareader.BaseImageAdapter.Companion.mergeBitmap
import ani.dantotsu.openLinkInBrowser
@@ -73,12 +74,17 @@ class ImageViewDialog : BottomSheetDialogFragment() {
if (image2 != null) openLinkInBrowser(image2.url)
true
}
val context = requireContext()
lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
val binding = _binding ?: return@launch
var bitmap = requireContext().loadBitmap_old(image, trans1 ?: listOf())
val bitmap2 = if (image2 != null) requireContext().loadBitmap_old(image2, trans2 ?: listOf()) else null
var bitmap = context.loadBitmap_old(image, trans1 ?: listOf())
var bitmap2 = if (image2 != null) context.loadBitmap_old(image2, trans2 ?: listOf()) else null
if (bitmap == null) {
bitmap = context.loadBitmap(image, trans1 ?: listOf())
bitmap2 = if (image2 != null) context.loadBitmap(image2, trans2 ?: listOf()) else null
}
bitmap = if (bitmap2 != null && bitmap != null) mergeBitmap(bitmap, bitmap2,) else bitmap

View File

@@ -57,17 +57,17 @@ abstract class BaseParser {
setUserText("Searching : ${mediaObj.mainName()}")
val results = search(mediaObj.mainName())
val sortedResults = if (results.isNotEmpty()) {
results.sortedByDescending { FuzzySearch.ratio(it.name, mediaObj.mainName()) }
results.sortedByDescending { FuzzySearch.ratio(it.name.lowercase(), mediaObj.mainName().lowercase()) }
} else {
emptyList()
}
response = sortedResults.firstOrNull()
if (response == null || FuzzySearch.ratio(response.name, mediaObj.mainName()) < 100) {
if (response == null || FuzzySearch.ratio(response.name.lowercase(), mediaObj.mainName().lowercase()) < 100) {
setUserText("Searching : ${mediaObj.nameRomaji}")
val romajiResults = search(mediaObj.nameRomaji)
val sortedRomajiResults = if (romajiResults.isNotEmpty()) {
romajiResults.sortedByDescending { FuzzySearch.ratio(it.name, mediaObj.nameRomaji) }
romajiResults.sortedByDescending { FuzzySearch.ratio(it.name.lowercase(), mediaObj.nameRomaji.lowercase()) }
} else {
emptyList()
}
@@ -78,10 +78,10 @@ abstract class BaseParser {
logger("No exact match found in results. Using closest match from RomajiResults.")
closestRomaji
} else {
val romajiRatio = FuzzySearch.ratio(closestRomaji?.name ?: "", mediaObj.nameRomaji)
val mainNameRatio = FuzzySearch.ratio(response.name, mediaObj.mainName())
logger("Fuzzy ratio for closest match in results: $mainNameRatio for ${response.name}")
logger("Fuzzy ratio for closest match in RomajiResults: $romajiRatio for ${closestRomaji?.name ?: "None"}")
val romajiRatio = FuzzySearch.ratio(closestRomaji?.name?.lowercase() ?: "", mediaObj.nameRomaji.lowercase())
val mainNameRatio = FuzzySearch.ratio(response.name.lowercase(), mediaObj.mainName().lowercase())
logger("Fuzzy ratio for closest match in results: $mainNameRatio for ${response.name.lowercase()}")
logger("Fuzzy ratio for closest match in RomajiResults: $romajiRatio for ${closestRomaji?.name?.lowercase() ?: "None"}")
if (romajiRatio > mainNameRatio) {
logger("RomajiResults has a closer match. Replacing response.")

View File

@@ -2,110 +2,81 @@ package ani.dantotsu.settings
import android.app.NotificationManager
import android.content.Context
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getSystemService
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
import ani.dantotsu.loadData
import com.bumptech.glide.Glide
import ani.dantotsu.settings.paging.AnimeExtensionAdapter
import ani.dantotsu.settings.paging.AnimeExtensionsViewModel
import ani.dantotsu.settings.paging.AnimeExtensionsViewModelFactory
import ani.dantotsu.settings.paging.OnAnimeInstallClickListener
import com.google.firebase.crashlytics.FirebaseCrashlytics
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class AnimeExtensionsFragment : Fragment(),
SearchQueryHandler {
SearchQueryHandler, OnAnimeInstallClickListener {
private var _binding: FragmentAnimeExtensionsBinding? = null
private val binding get() = _binding!!
val skipIcons = loadData("skip_extension_icons") ?: false
private val viewModel: AnimeExtensionsViewModel by viewModels {
AnimeExtensionsViewModelFactory(animeExtensionManager)
}
private lateinit var extensionsRecyclerView: RecyclerView
private lateinit var allextenstionsRecyclerView: RecyclerView
private val animeExtensionManager: AnimeExtensionManager = Injekt.get<AnimeExtensionManager>()
private val extensionsAdapter = AnimeExtensionsAdapter({ pkg ->
if (isAdded) { // Check if the fragment is currently added to its activity
val context = requireContext() // Store context in a variable
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
private val adapter by lazy {
AnimeExtensionAdapter(this)
}
if (pkg.hasUpdate) {
animeExtensionManager.updateExtension(pkg)
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Updating extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
FirebaseCrashlytics.getInstance().recordException(error)
Log.e("AnimeExtensionsAdapter", "Error: ", error) // Log the error
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Update failed: ${error.message}")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Update complete")
.setContentText("The extension has been successfully updated.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
} else {
animeExtensionManager.uninstallExtension(pkg.pkgName)
private val animeExtensionManager: AnimeExtensionManager = Injekt.get()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
binding.allAnimeExtensionsRecyclerView.isNestedScrollingEnabled = false
binding.allAnimeExtensionsRecyclerView.adapter = adapter
binding.allAnimeExtensionsRecyclerView.layoutManager = LinearLayoutManager(context)
(binding.allAnimeExtensionsRecyclerView.layoutManager as LinearLayoutManager).isItemPrefetchEnabled = true
lifecycleScope.launch {
viewModel.pagerFlow.collectLatest {
adapter.submitData(it)
}
}
}, skipIcons)
private val allExtensionsAdapter = AllAnimeExtensionsAdapter(lifecycleScope, { pkgName ->
viewModel.invalidatePager() // Force a refresh of the pager
return binding.root
}
override fun updateContentBasedOnQuery(query: String?) {
viewModel.setSearchQuery(query ?: "")
}
override fun onInstallClick(pkg: AnimeExtension.Available) {
val context = requireContext()
if (isAdded) {
val notificationManager =
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Start the installation process
animeExtensionManager.installExtension(pkgName)
animeExtensionManager.installExtension(pkg)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ installStep ->
@@ -136,63 +107,15 @@ class AnimeExtensionsFragment : Fragment(),
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setSmallIcon(R.drawable.ic_round_download_24)
.setContentTitle("Installation complete")
.setContentText("The extension has been successfully installed.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
viewModel.invalidatePager()
}
)
}
}, skipIcons)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
extensionsRecyclerView = binding.animeExtensionsRecyclerView
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
extensionsRecyclerView.adapter = extensionsAdapter
allextenstionsRecyclerView = binding.allAnimeExtensionsRecyclerView
allextenstionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
allextenstionsRecyclerView.adapter = allExtensionsAdapter
lifecycleScope.launch {
animeExtensionManager.installedExtensionsFlow.collect { extensions ->
extensionsAdapter.updateData(extensions)
}
}
lifecycleScope.launch {
combine(
animeExtensionManager.availableExtensionsFlow,
animeExtensionManager.installedExtensionsFlow
) { availableExtensions, installedExtensions ->
// Pair of available and installed extensions
Pair(availableExtensions, installedExtensions)
}.collect { pair ->
val (availableExtensions, installedExtensions) = pair
allExtensionsAdapter.updateData(availableExtensions, installedExtensions)
}
}
val extensionsRecyclerView: RecyclerView = binding.animeExtensionsRecyclerView
return binding.root
}
override fun updateContentBasedOnQuery(query: String?) {
if (query.isNullOrEmpty()) {
allExtensionsAdapter.filter("") // Reset the filter
allextenstionsRecyclerView.visibility = View.VISIBLE
extensionsRecyclerView.visibility = View.VISIBLE
} else {
allExtensionsAdapter.filter(query)
allextenstionsRecyclerView.visibility = View.VISIBLE
extensionsRecyclerView.visibility = View.GONE
}
}
override fun onDestroyView() {
@@ -200,158 +123,4 @@ class AnimeExtensionsFragment : Fragment(),
}
private class AnimeExtensionsAdapter(
private val onUninstallClicked: (AnimeExtension.Installed) -> Unit,
skipIcons: Boolean
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_INSTALLED
) {
val skipIcons = skipIcons
fun updateData(newExtensions: List<AnimeExtension.Installed>) {
submitList(newExtensions) // Use submitList instead of manual list handling
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_extension, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
holder.extensionIconImageView.setImageDrawable(extension.icon)
}
if (extension.hasUpdate) {
holder.closeTextView.text = "Update"
holder.closeTextView.setTextColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.warning
)
)
} else {
holder.closeTextView.text = "Uninstall"
}
holder.closeTextView.setOnClickListener {
onUninstallClicked(extension)
}
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
companion object {
val DIFF_CALLBACK_INSTALLED =
object : DiffUtil.ItemCallback<AnimeExtension.Installed>() {
override fun areItemsTheSame(
oldItem: AnimeExtension.Installed,
newItem: AnimeExtension.Installed
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: AnimeExtension.Installed,
newItem: AnimeExtension.Installed
): Boolean {
return oldItem == newItem
}
}
}
}
private class AllAnimeExtensionsAdapter(
private val coroutineScope: CoroutineScope,
private val onButtonClicked: (AnimeExtension.Available) -> Unit,
skipIcons: Boolean
) : ListAdapter<AnimeExtension.Available, AllAnimeExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_AVAILABLE
) {
val skipIcons = skipIcons
fun updateData(
newExtensions: List<AnimeExtension.Available>,
installedExtensions: List<AnimeExtension.Installed> = emptyList()
) {
coroutineScope.launch(Dispatchers.Default) {
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
val filteredExtensions = newExtensions.filter { it.pkgName !in installedPkgNames }
// Switch back to main thread to update UI
withContext(Dispatchers.Main) {
submitList(filteredExtensions)
}
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): AllAnimeExtensionsAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_extension_all, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position)
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
Glide.with(holder.itemView.context)
.load(extension.iconUrl)
.into(holder.extensionIconImageView)
}
holder.closeTextView.text = "Install"
holder.closeTextView.setOnClickListener {
onButtonClicked(extension)
}
}
fun filter(query: String) {
val filteredExtensions = if (query.isEmpty()) {
currentList
} else {
currentList.filter { it.name.contains(query, ignoreCase = true) }
}
submitList(filteredExtensions)
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
companion object {
val DIFF_CALLBACK_AVAILABLE =
object : DiffUtil.ItemCallback<AnimeExtension.Available>() {
override fun areItemsTheSame(
oldItem: AnimeExtension.Available,
newItem: AnimeExtension.Available
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: AnimeExtension.Available,
newItem: AnimeExtension.Available
): Boolean {
return oldItem == newItem
}
}
}
}
}

View File

@@ -13,26 +13,8 @@ class DevelopersDialogFragment : BottomSheetDialogFragment() {
private val binding get() = _binding!!
private val developers = arrayOf(
Developer("vorobyovgabriel","https://avatars.githubusercontent.com/u/99561687?s=120&v=4","Owner","https://github.com/vorobyovgabriel"),
Developer("brahmkshtriya","https://avatars.githubusercontent.com/u/69040506?s=120&v=4","Maintainer","https://github.com/brahmkshatriya"),
Developer("jeelpatel231","https://avatars.githubusercontent.com/u/33726155?s=120&v=4","Contributor","https://github.com/jeelpatel231"),
Developer("blatzar","https://avatars.githubusercontent.com/u/46196380?s=120&v=4","Contributor","https://github.com/Blatzar"),
Developer("bilibox","https://avatars.githubusercontent.com/u/1800580?s=120&v=4","Contributor","https://github.com/Bilibox"),
Developer("sutslec","https://avatars.githubusercontent.com/u/27722281?s=120&v=4","Contributor","https://github.com/Sutslec"),
Developer("4jx","https://avatars.githubusercontent.com/u/79868816?s=120&v=4","Contributor","https://github.com/4JX"),
Developer("xtrm-en","https://avatars.githubusercontent.com/u/26600206?s=120&v=4","Contributor","https://github.com/xtrm-en"),
Developer("scrazzz","https://avatars.githubusercontent.com/u/70033559?s=120&v=4","Contributor","https://github.com/scrazzz"),
Developer("defcoding","https://avatars.githubusercontent.com/u/39608887?s=120&v=4","Contributor","https://github.com/defcoding"),
Developer("adolar0042","https://avatars.githubusercontent.com/u/39769465?s=120&v=4","Contributor","https://github.com/adolar0042"),
Developer("diegopyl1209","https://avatars.githubusercontent.com/u/80992641?s=120&v=4","Contributor","https://github.com/diegopyl1209"),
Developer("sreekrishna2001","https://avatars.githubusercontent.com/u/67505103?s=120&v=4","Contributor","https://github.com/Sreekrishna2001"),
Developer("riimuru","https://avatars.githubusercontent.com/u/57333995?s=120&v=4","Contributor","https://github.com/riimuru"),
Developer("vu nguyen","https://avatars.githubusercontent.com/u/68330291?s=120&v=4","Contributor","https://github.com/hoangvu12"),
Developer("animejeff","https://avatars.githubusercontent.com/u/101831300?s=120&v=4","Contributor","https://github.com/AnimeJeff"),
Developer("antonydp","https://avatars.githubusercontent.com/u/38143733?s=120&v=4","Contributor","https://github.com/antonydp"),
Developer("tobybridle","https://avatars.githubusercontent.com/u/52335751?s=120&v=4","Contributor","https://github.com/TobyBridle"),
Developer("enimax","https://avatars.githubusercontent.com/u/107899019?s=120&v=4","Contributor","https://github.com/enimax-anime"),
Developer("vipulog","https://avatars.githubusercontent.com/u/90324465?s=120&v=4","Contributor","https://github.com/VipulOG")
Developer("rebelonion","https://avatars.githubusercontent.com/u/87634197?v=4","Owner and Maintainer","https://github.com/rebelonion"),
Developer("Wai What", "https://cdn.discordapp.com/avatars/928202695611908126/aeac4c867acbb8c3783356497055a426.webp?size=80", "Icon Designer", ""),
)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {

View File

@@ -1,55 +1,26 @@
package ani.dantotsu.settings
import android.annotation.SuppressLint
import android.app.NotificationManager
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Build.*
import android.os.Build.VERSION.*
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.text.Editable
import android.text.TextWatcher
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.AutoCompleteTextView
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.SearchView
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.*
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import ani.dantotsu.databinding.ActivityExtensionsBinding
import ani.dantotsu.home.AnimeFragment
import ani.dantotsu.home.MangaFragment
import ani.dantotsu.themes.ThemeManager
import com.bumptech.glide.Glide
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import eu.kanade.tachiyomi.data.notification.Notifications
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import javax.inject.Inject
class ExtensionsActivity : AppCompatActivity() {
private val restartMainActivity = object : OnBackPressedCallback(false) {
@@ -70,12 +41,14 @@ class ExtensionsActivity : AppCompatActivity() {
val viewPager = findViewById<ViewPager2>(R.id.viewPager)
viewPager.adapter = object : FragmentStateAdapter(this) {
override fun getItemCount(): Int = 2
override fun getItemCount(): Int = 4
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> AnimeExtensionsFragment()
1 -> MangaExtensionsFragment()
0 -> InstalledAnimeExtensionsFragment()
1 -> AnimeExtensionsFragment()
2 -> InstalledMangaExtensionsFragment()
3 -> MangaExtensionsFragment()
else -> AnimeExtensionsFragment()
}
}
@@ -83,28 +56,29 @@ class ExtensionsActivity : AppCompatActivity() {
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = when (position) {
0 -> "Anime" // Your tab title
1 -> "Manga" // Your tab title
0 -> "Installed Anime"
1 -> "Available Anime"
2 -> "Installed Manga"
3 -> "Available Manga"
else -> null
}
}.attach()
val searchView: SearchView = findViewById(R.id.searchView)
val searchView: AutoCompleteTextView = findViewById(R.id.searchViewText)
val extensionsHeader: LinearLayout = findViewById(R.id.extensionsHeader)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
searchView.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun onQueryTextChange(newText: String?): Boolean {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val currentFragment = supportFragmentManager.findFragmentByTag("f${viewPager.currentItem}")
if (currentFragment is SearchQueryHandler) {
currentFragment.updateContentBasedOnQuery(newText)
currentFragment.updateContentBasedOnQuery(s?.toString()?.trim())
}
return true
}
})

View File

@@ -0,0 +1,184 @@
package ani.dantotsu.settings
import android.app.NotificationManager
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
import ani.dantotsu.loadData
import com.google.firebase.crashlytics.FirebaseCrashlytics
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import kotlinx.coroutines.launch
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class InstalledAnimeExtensionsFragment : Fragment() {
private var _binding: FragmentAnimeExtensionsBinding? = null
private val binding get() = _binding!!
private lateinit var extensionsRecyclerView: RecyclerView
val skipIcons = loadData("skip_extension_icons") ?: false
private val animeExtensionManager: AnimeExtensionManager = Injekt.get()
private val extensionsAdapter = AnimeExtensionsAdapter({ pkg ->
if (isAdded) { // Check if the fragment is currently added to its activity
val context = requireContext() // Store context in a variable
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
if (pkg.hasUpdate) {
animeExtensionManager.updateExtension(pkg)
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Updating extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
FirebaseCrashlytics.getInstance().recordException(error)
Log.e("AnimeExtensionsAdapter", "Error: ", error) // Log the error
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Update failed: ${error.message}")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Update complete")
.setContentText("The extension has been successfully updated.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
} else {
animeExtensionManager.uninstallExtension(pkg.pkgName)
}
}
}, skipIcons)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
extensionsRecyclerView = binding.allAnimeExtensionsRecyclerView
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
extensionsRecyclerView.adapter = extensionsAdapter
lifecycleScope.launch {
animeExtensionManager.installedExtensionsFlow.collect { extensions ->
extensionsAdapter.updateData(extensions)
}
}
val extensionsRecyclerView: RecyclerView = binding.allAnimeExtensionsRecyclerView
return binding.root
}
override fun onDestroyView() {
super.onDestroyView();_binding = null
}
private class AnimeExtensionsAdapter(
private val onUninstallClicked: (AnimeExtension.Installed) -> Unit,
skipIcons: Boolean
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_INSTALLED
) {
val skipIcons = skipIcons
fun updateData(newExtensions: List<AnimeExtension.Installed>) {
submitList(newExtensions) // Use submitList instead of manual list handling
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_extension, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
holder.extensionIconImageView.setImageDrawable(extension.icon)
}
if (extension.hasUpdate) {
holder.closeTextView.text = "Update"
holder.closeTextView.setTextColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.warning
)
)
} else {
holder.closeTextView.text = "Uninstall"
}
holder.closeTextView.setOnClickListener {
onUninstallClicked(extension)
}
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
companion object {
val DIFF_CALLBACK_INSTALLED =
object : DiffUtil.ItemCallback<AnimeExtension.Installed>() {
override fun areItemsTheSame(
oldItem: AnimeExtension.Installed,
newItem: AnimeExtension.Installed
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: AnimeExtension.Installed,
newItem: AnimeExtension.Installed
): Boolean {
return oldItem == newItem
}
}
}
}
}

View File

@@ -0,0 +1,185 @@
package ani.dantotsu.settings
import android.app.NotificationManager
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
import ani.dantotsu.loadData
import com.google.firebase.crashlytics.FirebaseCrashlytics
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import kotlinx.coroutines.launch
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class InstalledMangaExtensionsFragment : Fragment() {
private var _binding: FragmentMangaExtensionsBinding? = null
private val binding get() = _binding!!
private lateinit var extensionsRecyclerView: RecyclerView
val skipIcons = loadData("skip_extension_icons") ?: false
private val mangaExtensionManager: MangaExtensionManager = Injekt.get()
private val extensionsAdapter = MangaExtensionsAdapter({ pkg ->
if (isAdded) { // Check if the fragment is currently added to its activity
val context = requireContext() // Store context in a variable
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
if (pkg.hasUpdate) {
mangaExtensionManager.updateExtension(pkg)
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Updating extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
FirebaseCrashlytics.getInstance().recordException(error)
Log.e("MangaExtensionsAdapter", "Error: ", error) // Log the error
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Update failed: ${error.message}")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Update complete")
.setContentText("The extension has been successfully updated.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
} else {
mangaExtensionManager.uninstallExtension(pkg.pkgName)
}
}
}, skipIcons)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentMangaExtensionsBinding.inflate(inflater, container, false)
extensionsRecyclerView = binding.allMangaExtensionsRecyclerView
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
extensionsRecyclerView.adapter = extensionsAdapter
lifecycleScope.launch {
mangaExtensionManager.installedExtensionsFlow.collect { extensions ->
extensionsAdapter.updateData(extensions)
}
}
val extensionsRecyclerView: RecyclerView = binding.allMangaExtensionsRecyclerView
return binding.root
}
override fun onDestroyView() {
super.onDestroyView();_binding = null
}
private class MangaExtensionsAdapter(
private val onUninstallClicked: (MangaExtension.Installed) -> Unit,
skipIcons: Boolean
) : ListAdapter<MangaExtension.Installed, MangaExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_INSTALLED
) {
val skipIcons = skipIcons
fun updateData(newExtensions: List<MangaExtension.Installed>) {
submitList(newExtensions) // Use submitList instead of manual list handling
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_extension, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
holder.extensionIconImageView.setImageDrawable(extension.icon)
}
if (extension.hasUpdate) {
holder.closeTextView.text = "Update"
holder.closeTextView.setTextColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.warning
)
)
} else {
holder.closeTextView.text = "Uninstall"
}
holder.closeTextView.setOnClickListener {
onUninstallClicked(extension)
}
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
companion object {
val DIFF_CALLBACK_INSTALLED =
object : DiffUtil.ItemCallback<MangaExtension.Installed>() {
override fun areItemsTheSame(
oldItem: MangaExtension.Installed,
newItem: MangaExtension.Installed
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: MangaExtension.Installed,
newItem: MangaExtension.Installed
): Boolean {
return oldItem == newItem
}
}
}
}
}

View File

@@ -2,150 +2,48 @@ package ani.dantotsu.settings
import android.app.NotificationManager
import android.content.Context
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.paging.PagingData
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentMangaBinding
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
import ani.dantotsu.loadData
import com.bumptech.glide.Glide
import com.google.firebase.crashlytics.FirebaseCrashlytics
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import ani.dantotsu.settings.paging.MangaExtensionAdapter
import ani.dantotsu.settings.paging.MangaExtensionsViewModel
import ani.dantotsu.settings.paging.MangaExtensionsViewModelFactory
import ani.dantotsu.settings.paging.OnMangaInstallClickListener
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest
class MangaExtensionsFragment : Fragment(),
SearchQueryHandler {
SearchQueryHandler, OnMangaInstallClickListener {
private var _binding: FragmentMangaExtensionsBinding? = null
private val binding get() = _binding!!
val skipIcons = loadData("skip_extension_icons") ?: false
private val viewModel: MangaExtensionsViewModel by viewModels {
MangaExtensionsViewModelFactory(mangaExtensionManager)
}
private lateinit var extensionsRecyclerView: RecyclerView
private lateinit var allextenstionsRecyclerView: RecyclerView
private val mangaExtensionManager: MangaExtensionManager = Injekt.get<MangaExtensionManager>()
private val extensionsAdapter = MangaExtensionsAdapter({ pkg ->
if (isAdded) { // Check if the fragment is currently added to its activity
val context = requireContext() // Store context in a variable
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
private val adapter by lazy {
MangaExtensionAdapter(this)
}
if (pkg.hasUpdate) {
mangaExtensionManager.updateExtension(pkg)
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Updating extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
FirebaseCrashlytics.getInstance().recordException(error)
Log.e("MangaExtensionsAdapter", "Error: ", error) // Log the error
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Update failed")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Update complete")
.setContentText("The extension has been successfully updated.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
} else {
mangaExtensionManager.uninstallExtension(pkg.pkgName)
}
}
}, skipIcons)
private val mangaExtensionManager: MangaExtensionManager = Injekt.get()
private val allExtensionsAdapter =
AllMangaExtensionsAdapter(lifecycleScope, { pkgName ->
if (isAdded) { // Check if the fragment is currently added to its activity
val context = requireContext()
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Start the installation process
mangaExtensionManager.installExtension(pkgName)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Installing extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
FirebaseCrashlytics.getInstance().recordException(error)
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Installation failed: ${error.message}")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setContentTitle("Installation complete")
.setContentText("The extension has been successfully installed.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
}
)
}
}, skipIcons)
override fun onCreateView(
inflater: LayoutInflater,
@@ -154,44 +52,72 @@ class MangaExtensionsFragment : Fragment(),
): View {
_binding = FragmentMangaExtensionsBinding.inflate(inflater, container, false)
extensionsRecyclerView = binding.mangaExtensionsRecyclerView
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
extensionsRecyclerView.adapter = extensionsAdapter
allextenstionsRecyclerView = binding.allMangaExtensionsRecyclerView
allextenstionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
allextenstionsRecyclerView.adapter = allExtensionsAdapter
binding.allMangaExtensionsRecyclerView.isNestedScrollingEnabled = false
binding.allMangaExtensionsRecyclerView.adapter = adapter
binding.allMangaExtensionsRecyclerView.layoutManager = LinearLayoutManager(context)
(binding.allMangaExtensionsRecyclerView.layoutManager as LinearLayoutManager).isItemPrefetchEnabled = true
lifecycleScope.launch {
mangaExtensionManager.installedExtensionsFlow.collect { extensions ->
extensionsAdapter.updateData(extensions)
viewModel.pagerFlow.collectLatest { pagingData ->
adapter.submitData(pagingData)
}
}
lifecycleScope.launch {
combine(
mangaExtensionManager.availableExtensionsFlow,
mangaExtensionManager.installedExtensionsFlow
) { availableExtensions, installedExtensions ->
// Pair of available and installed extensions
Pair(availableExtensions, installedExtensions)
}.collect { pair ->
val (availableExtensions, installedExtensions) = pair
allExtensionsAdapter.updateData(availableExtensions, installedExtensions)
}
}
val extensionsRecyclerView: RecyclerView = binding.mangaExtensionsRecyclerView
viewModel.invalidatePager() // Force a refresh of the pager
return binding.root
}
override fun updateContentBasedOnQuery(query: String?) {
if (query.isNullOrEmpty()) {
allExtensionsAdapter.filter("") // Reset the filter
allextenstionsRecyclerView.visibility = View.VISIBLE
extensionsRecyclerView.visibility = View.VISIBLE
} else {
allExtensionsAdapter.filter(query)
allextenstionsRecyclerView.visibility = View.VISIBLE
extensionsRecyclerView.visibility = View.GONE
viewModel.setSearchQuery(query ?: "")
}
override fun onInstallClick(pkg: MangaExtension.Available) {
if (isAdded) { // Check if the fragment is currently added to its activity
val context = requireContext()
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Start the installation process
mangaExtensionManager.installExtension(pkg)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ installStep ->
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_sync_24)
.setContentTitle("Installing extension")
.setContentText("Step: $installStep")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
},
{ error ->
FirebaseCrashlytics.getInstance().recordException(error)
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_ERROR
)
.setSmallIcon(R.drawable.ic_round_info_24)
.setContentTitle("Installation failed: ${error.message}")
.setContentText("Error: ${error.message}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationManager.notify(1, builder.build())
},
{
val builder = NotificationCompat.Builder(
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(R.drawable.ic_round_download_24)
.setContentTitle("Installation complete")
.setContentText("The extension has been successfully installed.")
.setPriority(NotificationCompat.PRIORITY_LOW)
notificationManager.notify(1, builder.build())
viewModel.invalidatePager()
}
)
}
}
@@ -199,165 +125,6 @@ class MangaExtensionsFragment : Fragment(),
super.onDestroyView();_binding = null
}
private class MangaExtensionsAdapter(
private val onUninstallClicked: (MangaExtension.Installed) -> Unit,
skipIcons: Boolean
) : ListAdapter<MangaExtension.Installed, MangaExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_INSTALLED
) {
val skipIcons = skipIcons
// Use submitList to update data
fun updateData(newExtensions: List<MangaExtension.Installed>) {
submitList(newExtensions)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_extension, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem from ListAdapter
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
holder.extensionIconImageView.setImageDrawable(extension.icon)
}
if (extension.hasUpdate) {
holder.closeTextView.text = "Update"
holder.closeTextView.setTextColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.warning
)
)
} else {
holder.closeTextView.text = "Uninstall"
}
holder.closeTextView.setOnClickListener {
onUninstallClicked(extension)
}
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
companion object {
val DIFF_CALLBACK_INSTALLED =
object : DiffUtil.ItemCallback<MangaExtension.Installed>() {
override fun areItemsTheSame(
oldItem: MangaExtension.Installed,
newItem: MangaExtension.Installed
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: MangaExtension.Installed,
newItem: MangaExtension.Installed
): Boolean {
return oldItem == newItem
}
}
}
}
private class AllMangaExtensionsAdapter(
private val coroutineScope: CoroutineScope,
private val onButtonClicked: (MangaExtension.Available) -> Unit,
skipIcons: Boolean
) : ListAdapter<MangaExtension.Available, AllMangaExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_AVAILABLE
) {
init {
setHasStableIds(true)
}
val skipIcons = skipIcons
// Use submitList to update the data
fun updateData(
newExtensions: List<MangaExtension.Available>,
installedExtensions: List<MangaExtension.Installed> = emptyList()
) {
coroutineScope.launch(Dispatchers.Default) {
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
val filteredExtensions = newExtensions.filter { it.pkgName !in installedPkgNames }
// Switch back to main thread to update UI
withContext(Dispatchers.Main) {
submitList(filteredExtensions)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_extension_all, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem from ListAdapter
holder.extensionNameTextView.text = extension.name
if (!skipIcons) {
Glide.with(holder.itemView.context)
.load(extension.iconUrl)
.into(holder.extensionIconImageView)
}
holder.closeTextView.text = "Install"
holder.closeTextView.setOnClickListener {
onButtonClicked(extension)
}
}
// Filtering function
fun filter(query: String) {
val filteredExtensions = if (query.isEmpty()) {
currentList
} else {
currentList.filter { it.name.contains(query, ignoreCase = true) }
}
submitList(filteredExtensions)
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
}
companion object {
val DIFF_CALLBACK_AVAILABLE =
object : DiffUtil.ItemCallback<MangaExtension.Available>() {
override fun areItemsTheSame(
oldItem: MangaExtension.Available,
newItem: MangaExtension.Available
): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(
oldItem: MangaExtension.Available,
newItem: MangaExtension.Available
): Boolean {
return oldItem == newItem
}
}
}
}
}

View File

@@ -33,6 +33,7 @@ import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
import ani.dantotsu.themes.ThemeManager
import com.google.android.material.snackbar.Snackbar
import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.network.NetworkPreferences
import io.noties.markwon.Markwon
@@ -101,7 +102,13 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
binding.settingsUseMaterialYou.isChecked = getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getBoolean("use_material_you", false)
binding.settingsUseMaterialYou.setOnCheckedChangeListener { _, isChecked ->
getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).edit().putBoolean("use_material_you", isChecked).apply()
Toast.makeText(this, "Restart app to apply changes", Toast.LENGTH_LONG).show()
restartApp()
}
binding.settingsUseOLED.isChecked = getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getBoolean("use_oled", false)
binding.settingsUseOLED.setOnCheckedChangeListener { _, isChecked ->
getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).edit().putBoolean("use_oled", isChecked).apply()
restartApp()
}
val themeString = getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getString("theme", "PURPLE")!!
@@ -111,12 +118,9 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
binding.themeSwitcher.setOnItemClickListener { _, _, i, _ ->
getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).edit().putString("theme", ThemeManager.Companion.Theme.values()[i].theme).apply()
ActivityHelper.shouldRefreshMainActivity = true
//ActivityHelper.shouldRefreshMainActivity = true
binding.themeSwitcher.clearFocus()
Refresh.all()
finish()
startActivity(Intent(this, SettingsActivity::class.java))
initActivity(this)
restartApp()
}
@@ -410,7 +414,7 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
}
}
var curTime = loadData<Int>("subscriptions_time_r") ?: defaultTime
var curTime = loadData<Int>("subscriptions_time_s") ?: defaultTime
val timeNames = timeMinutes.map {
val mins = it % 60
val hours = it / 60
@@ -423,7 +427,7 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
speedDialog.setSingleChoiceItems(timeNames, curTime) { dialog, i ->
curTime = i
binding.settingsSubscriptionsTime.text = getString(R.string.subscriptions_checking_time_s, timeNames[i])
saveData("subscriptions_time_r", curTime)
saveData("subscriptions_time_s", curTime)
dialog.dismiss()
startSubscription(true)
}.show()
@@ -586,4 +590,18 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
}
}
}
private fun restartApp() {
Snackbar.make(
binding.root,
R.string.restart_app, Snackbar.LENGTH_SHORT
).apply {
val mainIntent =
Intent.makeRestartActivityTask(context.packageManager.getLaunchIntentForPackage(context.packageName)!!.component)
setAction("Do it!") {
context.startActivity(mainIntent)
Runtime.getRuntime().exit(0)
}
show()
}
}
}

View File

@@ -3,8 +3,10 @@ package ani.dantotsu.settings
import android.app.DownloadManager
import android.content.ActivityNotFoundException
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -26,6 +28,12 @@ class SettingsDialogFragment : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val window = dialog?.window
window?.statusBarColor = Color.CYAN
val typedValue = TypedValue()
val theme = requireContext().theme
theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValue, true)
window?.navigationBarColor = typedValue.data
if (Anilist.token != null) {
binding.settingsLogin.setText(R.string.logout)

View File

@@ -0,0 +1,162 @@
package ani.dantotsu.settings.paging
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingDataAdapter
import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.paging.cachedIn
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
class AnimeExtensionsViewModelFactory(
private val animeExtensionManager: AnimeExtensionManager
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return AnimeExtensionsViewModel(animeExtensionManager) as T
}
}
class AnimeExtensionsViewModel(
private val animeExtensionManager: AnimeExtensionManager
) : ViewModel() {
private val searchQuery = MutableStateFlow("")
private var currentPagingSource: AnimeExtensionPagingSource? = null
fun setSearchQuery(query: String) {
searchQuery.value = query
}
fun invalidatePager() {
currentPagingSource?.invalidate()
}
@OptIn(ExperimentalCoroutinesApi::class)
val pagerFlow: Flow<PagingData<AnimeExtension.Available>> = searchQuery.flatMapLatest { query ->
Pager(
PagingConfig(
pageSize = 15,
initialLoadSize = 15,
prefetchDistance = 15
)
) {
AnimeExtensionPagingSource(
animeExtensionManager.availableExtensionsFlow,
animeExtensionManager.installedExtensionsFlow,
searchQuery
).also { currentPagingSource = it }
}.flow
}.cachedIn(viewModelScope)
}
class AnimeExtensionPagingSource(
private val availableExtensionsFlow: StateFlow<List<AnimeExtension.Available>>,
private val installedExtensionsFlow: StateFlow<List<AnimeExtension.Installed>>,
private val searchQuery: StateFlow<String>
) : PagingSource<Int, AnimeExtension.Available>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AnimeExtension.Available> {
val position = params.key ?: 0
val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet()
val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions }
val query = searchQuery.first()
val filteredExtensions = if (query.isEmpty()) {
availableExtensions
} else {
availableExtensions.filter { it.name.contains(query, ignoreCase = true) }
}
return try {
val sublist = filteredExtensions.subList(
fromIndex = position,
toIndex = (position + params.loadSize).coerceAtMost(filteredExtensions.size)
)
LoadResult.Page(
data = sublist,
prevKey = if (position == 0) null else position - params.loadSize,
nextKey = if (position + params.loadSize >= filteredExtensions.size) null else position + params.loadSize
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, AnimeExtension.Available>): Int? {
return null
}
}
class AnimeExtensionAdapter(private val clickListener: OnAnimeInstallClickListener) :
PagingDataAdapter<AnimeExtension.Available, AnimeExtensionAdapter.AnimeExtensionViewHolder>(
DIFF_CALLBACK
) {
private val skipIcons = loadData("skip_extension_icons") ?: false
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<AnimeExtension.Available>() {
override fun areItemsTheSame(oldItem: AnimeExtension.Available, newItem: AnimeExtension.Available): Boolean {
// Your logic here
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(oldItem: AnimeExtension.Available, newItem: AnimeExtension.Available): Boolean {
// Your logic here
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AnimeExtensionViewHolder {
val binding = ItemExtensionAllBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return AnimeExtensionViewHolder(binding)
}
override fun onBindViewHolder(holder: AnimeExtensionViewHolder, position: Int) {
val extension = getItem(position)
if (extension != null) {
if (!skipIcons) {
Glide.with(holder.itemView.context)
.load(extension.iconUrl)
.into(holder.extensionIconImageView)
}
holder.bind(extension)
}
}
inner class AnimeExtensionViewHolder(private val binding: ItemExtensionAllBinding) : RecyclerView.ViewHolder(binding.root) {
init {
binding.closeTextView.setOnClickListener {
val extension = getItem(bindingAdapterPosition)
if (extension != null) {
clickListener.onInstallClick(extension)
}
}
}
val extensionIconImageView: ImageView = binding.extensionIconImageView
fun bind(extension: AnimeExtension.Available) {
binding.extensionNameTextView.text = extension.name
}
}
}
interface OnAnimeInstallClickListener {
fun onInstallClick(pkg: AnimeExtension.Available)
}

View File

@@ -0,0 +1,164 @@
package ani.dantotsu.settings.paging
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingDataAdapter
import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.paging.cachedIn
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import java.lang.Math.min
class MangaExtensionsViewModelFactory(
private val mangaExtensionManager: MangaExtensionManager
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return MangaExtensionsViewModel(mangaExtensionManager) as T
}
}
class MangaExtensionsViewModel(
private val mangaExtensionManager: MangaExtensionManager
) : ViewModel() {
private val searchQuery = MutableStateFlow("")
private var currentPagingSource: MangaExtensionPagingSource? = null
fun setSearchQuery(query: String) {
searchQuery.value = query
}
fun invalidatePager() {
currentPagingSource?.invalidate()
}
@OptIn(ExperimentalCoroutinesApi::class)
val pagerFlow: Flow<PagingData<MangaExtension.Available>> = searchQuery.flatMapLatest { query ->
Pager(
PagingConfig(
pageSize = 15,
initialLoadSize = 15,
prefetchDistance = 15
)
) {
MangaExtensionPagingSource(
mangaExtensionManager.availableExtensionsFlow,
mangaExtensionManager.installedExtensionsFlow,
searchQuery
).also { currentPagingSource = it }
}.flow
}.cachedIn(viewModelScope)
}
class MangaExtensionPagingSource(
private val availableExtensionsFlow: StateFlow<List<MangaExtension.Available>>,
private val installedExtensionsFlow: StateFlow<List<MangaExtension.Installed>>,
private val searchQuery: StateFlow<String>
) : PagingSource<Int, MangaExtension.Available>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MangaExtension.Available> {
val position = params.key ?: 0
val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet()
val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions }
val query = searchQuery.first()
val filteredExtensions = if (query.isEmpty()) {
availableExtensions
} else {
availableExtensions.filter { it.name.contains(query, ignoreCase = true) }
}
return try {
val sublist = filteredExtensions.subList(
fromIndex = position,
toIndex = (position + params.loadSize).coerceAtMost(filteredExtensions.size)
)
LoadResult.Page(
data = sublist,
prevKey = if (position == 0) null else position - params.loadSize,
nextKey = if (position + params.loadSize >= filteredExtensions.size) null else position + params.loadSize
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, MangaExtension.Available>): Int? {
return null
}
}
class MangaExtensionAdapter(private val clickListener: OnMangaInstallClickListener) :
PagingDataAdapter<MangaExtension.Available, MangaExtensionAdapter.MangaExtensionViewHolder>(
DIFF_CALLBACK
) {
private val skipIcons = loadData("skip_extension_icons") ?: false
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<MangaExtension.Available>() {
override fun areItemsTheSame(oldItem: MangaExtension.Available, newItem: MangaExtension.Available): Boolean {
return oldItem.pkgName == newItem.pkgName
}
override fun areContentsTheSame(oldItem: MangaExtension.Available, newItem: MangaExtension.Available): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MangaExtensionViewHolder {
val binding = ItemExtensionAllBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MangaExtensionViewHolder(binding)
}
override fun onBindViewHolder(holder: MangaExtensionViewHolder, position: Int) {
val extension = getItem(position)
if (extension != null) {
if (!skipIcons) {
Glide.with(holder.itemView.context)
.load(extension.iconUrl)
.into(holder.extensionIconImageView)
}
holder.bind(extension)
}
}
inner class MangaExtensionViewHolder(private val binding: ItemExtensionAllBinding) : RecyclerView.ViewHolder(binding.root) {
init {
binding.closeTextView.setOnClickListener {
val extension = getItem(bindingAdapterPosition)
if (extension != null) {
clickListener.onInstallClick(extension)
}
}
}
val extensionIconImageView: ImageView = binding.extensionIconImageView
fun bind(extension: MangaExtension.Available) {
binding.extensionNameTextView.text = extension.name
}
}
}
interface OnMangaInstallClickListener {
fun onInstallClick(pkg: MangaExtension.Available)
}

View File

@@ -40,7 +40,7 @@ class AlarmReceiver : BroadcastReceiver() {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val curTime = loadData<Int>("subscriptions_time_r", context) ?: defaultTime
val curTime = loadData<Int>("subscriptions_time_s", context) ?: defaultTime
if (timeMinutes[curTime] > 0)
alarmManager.setRepeating(

View File

@@ -16,8 +16,8 @@ import kotlinx.coroutines.launch
@SuppressLint("MissingPermission")
class Subscription {
companion object {
const val defaultTime = 3
val timeMinutes = arrayOf(0L, 120, 180, 240, 360, 480, 720, 1440)
const val defaultTime = 1
val timeMinutes = arrayOf(0L, 720, 1440)
private var alreadyStarted = false
fun Context.startSubscription(force: Boolean = false) {

View File

@@ -22,7 +22,7 @@ class SubscriptionWorker(val context: Context, params: WorkerParameters) : Corou
private const val SUBSCRIPTION_WORK_NAME = "work_subscription"
fun enqueue(context: Context) {
val curTime = loadData<Int>("subscriptions_time_r") ?: defaultTime
val curTime = loadData<Int>("subscriptions_time_s") ?: defaultTime
if(timeMinutes[curTime]>0L) {
val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
val periodicSyncDataWork = PeriodicWorkRequest.Builder(

View File

@@ -1,42 +1,50 @@
package ani.dantotsu.themes
import android.content.Context
import android.content.res.Configuration
import ani.dantotsu.R
class ThemeManager(private val context: Context) {
fun applyTheme() {
val useOLED = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getBoolean("use_oled", false) && isDarkThemeActive(context)
if(context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getBoolean("use_material_you", false)){
return
}
when (context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getString("theme", "PURPLE")!!) {
"PURPLE" -> {
context.setTheme(R.style.Theme_Dantotsu_Purple)
}
//"MONOCHROME" -> {
// context.setTheme(R.style.Theme_Dantotsu_Monochrome)
//}
"BLUE" -> {
context.setTheme(R.style.Theme_Dantotsu_Blue)
}
"GREEN" -> {
context.setTheme(R.style.Theme_Dantotsu_Green)
}
"PINK" -> {
context.setTheme(R.style.Theme_Dantotsu_Pink)
}
else -> {
context.setTheme(R.style.Theme_Dantotsu_Purple)
}
val theme = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getString("theme", "PURPLE")!!
val themeToApply = when (theme) {
"PURPLE" -> if (useOLED) R.style.Theme_Dantotsu_PurpleOLED else R.style.Theme_Dantotsu_Purple
"BLUE" -> if (useOLED) R.style.Theme_Dantotsu_BlueOLED else R.style.Theme_Dantotsu_Blue
"GREEN" -> if (useOLED) R.style.Theme_Dantotsu_GreenOLED else R.style.Theme_Dantotsu_Green
"PINK" -> if (useOLED) R.style.Theme_Dantotsu_PinkOLED else R.style.Theme_Dantotsu_Pink
"RED" -> if (useOLED) R.style.Theme_Dantotsu_RedOLED else R.style.Theme_Dantotsu_Red
"LAVENDER" -> if (useOLED) R.style.Theme_Dantotsu_LavenderOLED else R.style.Theme_Dantotsu_Lavender
"MONOCHROME (BETA)" -> if (useOLED) R.style.Theme_Dantotsu_MonochromeOLED else R.style.Theme_Dantotsu_Monochrome
else -> if (useOLED) R.style.Theme_Dantotsu_PurpleOLED else R.style.Theme_Dantotsu_Purple
}
context.setTheme(themeToApply)
}
private fun isDarkThemeActive(context: Context): Boolean {
return when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> true
Configuration.UI_MODE_NIGHT_NO -> false
Configuration.UI_MODE_NIGHT_UNDEFINED -> false
else -> false
}
}
companion object{
enum class Theme(val theme: String) {
PURPLE("PURPLE"),
BLUE("BLUE"),
GREEN("GREEN"),
PINK("PINK");
//MONOCHROME("MONOCHROME");
PINK("PINK"),
RED("RED"),
LAVENDER("LAVENDER"),
MONOCHROME("MONOCHROME (BETA)");
companion object {
fun fromString(value: String): Theme {

View File

@@ -11,7 +11,7 @@ import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.Serializable
data class Track(val url: String, val lang: String)
data class Track(val url: String, val lang: String) : Serializable
open class Video(
val url: String = "",

View File

@@ -108,8 +108,11 @@ internal class AnimeExtensionInstaller(private val context: Context) {
// Get the current download status
.map {
downloadManager.query(query).use { cursor ->
cursor.moveToFirst()
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
if (cursor.moveToFirst()) {
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
} else {
DownloadManager.STATUS_FAILED
}
}
}
// Ignore duplicate results

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Color when the chip is selected -->
<item android:color="?attr/colorSurface" android:state_selected="true"/>
<!-- Color when the chip is not selected -->
<item android:color="?attr/colorOnSurface"/>
</selector>

View File

@@ -1,173 +1,377 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:viewportWidth="70"
android:viewportHeight="70"
android:width="248.0315dp"
android:height="248.0315dp">
android:name="vector"
android:width="768dp"
android:height="768dp"
android:viewportWidth="768"
android:viewportHeight="768">
<group
android:translateX="-73.31698"
android:translateY="-111.8453">
clip-path
android:name="clip"
android:pathData="M32,32m-32,0a32,32 0,1 1,64 0a32,32 0,1 1,-64 0" />
<group
android:name="zoomGroup_1"
android:pivotX="32"
android:pivotY="32"
android:scaleX="0"
android:scaleY="0">
<path
android:fillColor="#5a189a"
android:pathData="M140.3172 146.8457A32 32 0 0 1 76.31718 146.8457A32 32 0 0 1 140.3172 146.8457Z"
android:strokeWidth="0.264583" />
</group>
<group
android:name="zoomGroup_2"
android:pivotX="32"
android:pivotY="32"
android:scaleX="0"
android:scaleY="0">
<path
android:fillColor="#7b2cbf"
android:pathData="M128.3172 146.8457A20 20 0 0 1 88.31718 146.8457A20 20 0 0 1 128.3172 146.8457Z"
android:strokeWidth="0.264583" />
</group>
<group
android:name="zoomGroup_3"
android:pivotX="32"
android:pivotY="32"
android:scaleX="0"
android:scaleY="0">
<path
android:fillColor="#9d4edd"
android:pathData="M124.3172 146.8457A16 16 0 0 1 92.31718 146.8457A16 16 0 0 1 124.3172 146.8457Z"
android:strokeWidth="0.264583" />
</group>
<group
android:name="translateGroup_1"
android:pivotX="32"
android:pivotY="32"
android:scaleX="1"
android:scaleY="1"
android:translateX="-35">
<path
android:fillColor="#10002b"
android:pathData="M108.33606 114.84532a32 32 0 0 0 -31.99908 32.00011 32 32 0 0 0 7.100859 20.00033h24.898221zm-19.939351 27.35544l0.49196 0.925c0.01823 0.19615 -0.05452 0.22438 -0.218592 0.0842 -0.601567 0.19615 -1.212649 0.34989 -1.832446 0.46198v1.80765h2.18798v0.7984h-0.738456v5.12785h-0.546737v-5.12785h-0.902787v1.80764c0 1.42908 -0.327663 2.56382 -0.983919 3.40444l-0.410311 -0.71468 0.24598 -0.33642h-2.132687v0.79892h-0.547253v-8.74262h0.519865c0.145836 0.028 0.154993 0.11207 0.02739 0.25218v2.77399h1.011825v-3.19463h0.437183c0.14583 0.028 0.154993 0.11208 0.02739 0.25218v2.94245h1.039213v0.67231H85.03309v0.33642c0.401049 0.33625 0.720064 0.65862 0.957048 0.96686l-0.328146 0.7984c-0.164065 -0.28021 -0.373689 -0.60213 -0.628902 -0.96634v1.93321h-0.464571v-1.76527c-0.200525 0.5324 -0.419307 0.96652 -0.656291 1.30277l-0.300757 -0.67231c0.38282 -0.5324 0.692682 -1.17717 0.929659 -1.93374h-0.984436v3.44682h2.32389v0.50436c0.273436 -0.47636 0.41031 -1.17699 0.41031 -2.10168v-5.2958l0.519865 0.21033c0.619804 -0.11209 1.148442 -0.36476 1.58595 -0.75706zm3.636471 0.37827h0.547253c0.218753 0.028 0.245713 0.14027 0.08165 0.33641v2.6479c0.893241 0.3923 1.795859 0.92482 2.707328 1.59732l-0.328145 0.96687c-0.966157 -0.75657 -1.759385 -1.2609 -2.379183 -1.51309v4.37131H92.03318Zm-6.398576 0.37879l0.492476 0.2098c0.07292 0.0841 0.0546 0.15429 -0.05478 0.21033 -0.109377 0.5884 -0.246245 1.17681 -0.410311 1.76526l-0.437182 -0.25218c0.182291 -0.67249 0.318646 -1.31675 0.409794 -1.93321zm-1.531173 0.12609c0.145836 0.56042 0.246068 1.17648 0.300757 1.84898l-0.464571 0.25218c-0.09115 -0.84063 -0.191897 -1.45668 -0.301274 -1.84898zm15.50448 0.0419c0.273442 0.58844 0.537509 1.3311 0.792719 2.22778l-0.628905 0.50436c-0.255208 -0.89668 -0.519791 -1.65316 -0.793233 -2.26963zm2.296499 0.21033l0.65629 0.29404c0.1823 0.0841 0.1823 0.21014 0 0.37827 -0.21875 2.26971 -0.65632 3.92311 -1.31258 4.9599 -0.58334 0.92468 -1.376045 1.63916 -2.378665 2.14354l-0.492477 -0.88263c0.98439 -0.42032 1.740982 -1.0087 2.269632 -1.76527 0.65626 -0.95272 1.07551 -2.66202 1.2578 -5.12785zm-4.019391 0.37827c0.273441 0.67251 0.546664 1.48486 0.820105 2.43758l-0.628902 0.50436c-0.236984 -0.86865 -0.501046 -1.68101 -0.792717 -2.43758z"
android:strokeWidth="0.264583" />
<path
android:fillColor="#10002b"
android:pathData="M108.33574 170.84552H87.19698a32 32 0 0 0 21.13876 8.00003z"
android:strokeWidth="0.264583" />
</group>
<group
android:name="translateGroup_2"
android:pivotX="32"
android:pivotY="32"
android:scaleX="1"
android:scaleY="1"
android:translateX="35">
<path
android:fillColor="#10002b"
android:pathData="M108.29698 134.84565v23.99957a12 12 0 0 0 11.99979 -11.99979 12 12 0 0 0 -11.99979 -11.99978z"
android:strokeWidth="0.264583" />
<path
android:fillColor="#10002b"
android:pathData="M108.29698 178.84555a32 32 0 0 0 32.00012 -32.00012 32 32 0 0 0 -32.00012 -32.00011v8.00003a24 24 0 0 1 24.00009 24.00008 24 24 0 0 1 -24.00009 24.00009z"
android:strokeWidth="0.264583" />
android:name="wrapper"
android:pivotX="384"
android:pivotY="384">
<clip-path
android:name="clippath"
android:pathData="M 384 128.04 C 329.836 127.869 276.99 144.889 233.11 176.638 C 189.23 208.387 156.539 253.255 139.769 304.75 C 122.999 356.244 122.999 411.756 139.769 463.25 C 156.539 514.745 189.23 559.613 233.11 591.362 C 276.99 623.111 329.836 640.131 384 639.96 C 451.869 639.96 517.028 612.974 565.019 564.991 C 613.01 517.008 640 451.859 640 384 C 640 316.141 613.01 250.992 565.019 203.009 C 517.028 155.026 451.869 128.04 384 128.04 Z"/>
<group android:name="group">
<group android:name="group_1">
<path
android:name="path"
android:pathData="M 128 128 L 640 128 L 640 639.96 L 128 639.96 Z"
android:fillColor="#ff00f4"
android:strokeWidth="1"/>
<group
android:name="group_12"
android:pivotX="384"
android:pivotY="384">
<path
android:name="path_2"
android:pathData="M 384 211.74 C 338.331 211.74 294.486 229.901 262.194 262.194 C 229.901 294.486 211.74 338.331 211.74 384 C 211.74 429.669 229.901 473.514 262.194 505.806 C 294.486 538.099 338.331 556.26 384 556.26 C 429.669 556.26 473.514 538.099 505.806 505.806 C 538.099 473.514 556.26 429.669 556.26 384 C 556.26 338.331 538.099 294.486 505.806 262.194 C 473.514 229.901 429.669 211.74 384 211.74 Z"
android:fillColor="#d300e5"
android:strokeWidth="1"/>
</group>
</group>
<group android:name="group_2">
<group android:name="group_7">
<group android:name="group_10">
<group
android:name="group_11"
android:pivotX="94"
android:pivotY="440"
android:rotation="-90">
<path
android:name="path_1"
android:pathData="M 128 128 L 128 463.26 C 151.32 466.96 175.23 468.89 199.58 468.89 C 411.17 468.89 588.92 323.99 639.01 128 L 128 128 Z"
android:fillColor="#7000b8"
android:strokeWidth="1"/>
<clip-path
android:name="mask_2"
android:pathData="M 128 128 L 128 463.26 C 151.32 466.96 175.23 468.89 199.58 468.89 C 411.17 468.89 588.92 323.99 639.01 128 L 128 128 Z"/>
</group>
</group>
<group
android:name="group_13"
android:pivotX="384"
android:pivotY="384">
<clip-path
android:name="mask_1"
android:pathData="M 384 211.74 C 338.331 211.74 294.486 229.901 262.194 262.194 C 229.901 294.486 211.74 338.331 211.74 384 C 211.74 429.669 229.901 473.514 262.194 505.806 C 294.486 538.099 338.331 556.26 384 556.26 C 429.669 556.26 473.514 538.099 505.806 505.806 C 538.099 473.514 556.26 429.669 556.26 384 C 556.26 338.331 538.099 294.486 505.806 262.194 C 473.514 229.901 429.669 211.74 384 211.74 Z"/>
<group
android:name="group_9"
android:pivotX="94"
android:pivotY="440"
android:rotation="-90">
<path
android:name="path_3"
android:pathData="M 128 128 L 128 463.26 C 151.32 466.96 175.23 468.89 199.58 468.89 C 411.17 468.89 588.92 323.99 639.01 128 L 128 128 Z"
android:fillColor="#9000d1"
android:strokeWidth="1"/>
</group>
</group>
<group
android:name="group_6"
android:pivotX="94"
android:pivotY="440"
android:scaleX="1.2"
android:scaleY="1.2"
android:rotation="-5"/>
</group>
<group
android:name="group_8"
android:pivotX="94"
android:pivotY="440"
android:rotation="-90">
<group
android:name="group_14"
android:pivotX="94"
android:pivotY="440">
<path
android:name="path_4"
android:pathData="M 539.28 128 C 503.71 317.07 337.72 460.12 138.31 460.12 C 134.86 460.12 131.42 460.06 128 459.98 L 128 465.73 C 168.23 476.19 210.43 481.78 253.93 481.78 C 409.53 481.78 548.48 410.55 640 298.94 L 640 128.01 L 539.28 128.01 Z"
android:fillColor="#a800d9"
android:strokeWidth="1"/>
</group>
</group>
</group>
<group
android:name="group_3"
android:translateX="-360">
<path
android:name="path_6"
android:pathData="M 481.82 384 C 481.82 438.03 438.02 481.82 384 481.82 L 0 481.82 L 0 286.18 L 384 286.18 C 438.02 286.18 481.82 329.98 481.82 384 Z"
android:fillColor="#1f1f30"
android:strokeWidth="1"/>
</group>
<group
android:name="group_4"
android:pivotX="384"
android:pivotY="384"
android:scaleX="1.5"
android:scaleY="1.5">
<path
android:name="path_5"
android:pathData="M 44.26 128 C 44.26 174.25 81.75 211.74 128 211.74 L 384 211.74 C 479.13 211.74 556.26 288.86 556.26 384 C 556.26 479.13 479.14 556.26 384 556.26 L 128 556.26 C 81.76 556.26 44.28 593.73 44.26 639.97 L 768 639.97 L 768 128 L 44.26 128 Z"
android:fillColor="#1f1f30"
android:strokeWidth="1"/>
</group>
<group
android:name="group_5"
android:pivotX="384"
android:pivotY="384"
android:scaleX="3"
android:scaleY="3"
android:rotation="-15">
<path
android:name="path_7"
android:pathData="M 442 366.7 L 365.98 322.81 C 352.66 315.12 336.02 324.73 336.02 340.11 L 336.02 427.89 C 336.02 443.27 352.67 452.88 365.98 445.19 L 442 401.3 C 455.32 393.61 455.32 374.39 442 366.7 Z"
android:fillColor="#efe7ff"
android:fillAlpha="0"
android:strokeWidth="1"/>
</group>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="zoomGroup_1">
<target android:name="wrapper">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:duration="300"
android:interpolator="@android:anim/overshoot_interpolator"
android:propertyName="scaleX"
android:startOffset="600"
android:duration="500"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
<objectAnimator
android:duration="300"
android:interpolator="@android:anim/overshoot_interpolator"
android:propertyName="scaleY"
android:startOffset="600"
android:duration="500"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
</set>
</aapt:attr>
</target>
<target android:name="zoomGroup_2">
<target android:name="group_6">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:duration="300"
android:interpolator="@android:anim/overshoot_interpolator"
android:propertyName="scaleX"
android:startOffset="300"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
android:propertyName="rotation"
android:startOffset="350"
android:duration="550"
android:valueFrom="-10"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
<objectAnimator
android:propertyName="scaleX"
android:startOffset="350"
android:duration="300"
android:interpolator="@android:anim/overshoot_interpolator"
android:propertyName="scaleY"
android:startOffset="300"
android:valueFrom="0"
android:valueFrom="1.2"
android:valueTo="1"
android:valueType="floatType" />
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="scaleY"
android:startOffset="350"
android:duration="300"
android:valueFrom="1.2"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</set>
</aapt:attr>
</target>
<target android:name="zoomGroup_3">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:duration="300"
android:interpolator="@android:anim/overshoot_interpolator"
android:propertyName="scaleX"
android:startOffset="0"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
<objectAnimator
android:duration="300"
android:interpolator="@android:anim/overshoot_interpolator"
android:propertyName="scaleY"
android:startOffset="0"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
</set>
</aapt:attr>
</target>
<target android:name="translateGroup_1">
<target android:name="group_3">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="translateX"
android:startOffset="900"
android:valueFrom="-35"
android:startOffset="250"
android:duration="400"
android:valueFrom="-360"
android:valueTo="0"
android:valueType="floatType" />
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
</aapt:attr>
</target>
<target android:name="translateGroup_2">
<target android:name="group_4">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="scaleX"
android:startOffset="400"
android:duration="350"
android:valueFrom="1.5"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="scaleY"
android:startOffset="400"
android:duration="350"
android:valueFrom="1.5"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</set>
</aapt:attr>
</target>
<target android:name="path_7">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="translateX"
android:startOffset="900"
android:valueFrom="35"
android:propertyName="fillAlpha"
android:startOffset="350"
android:duration="550"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="group_5">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="rotation"
android:startOffset="350"
android:duration="550"
android:valueFrom="-45"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:anim/decelerate_interpolator"/>
<objectAnimator
android:propertyName="scaleX"
android:startOffset="350"
android:duration="550"
android:valueFrom="3"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="scaleY"
android:startOffset="350"
android:duration="550"
android:valueFrom="3"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</set>
</aapt:attr>
</target>
<target android:name="group_8">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="rotation"
android:startOffset="100"
android:duration="350"
android:valueFrom="-90"
android:valueTo="0"
android:valueType="floatType" />
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="group_9">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="rotation"
android:startOffset="100"
android:duration="350"
android:valueFrom="-90"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="scaleX"
android:duration="350"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="350"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</set>
</aapt:attr>
</target>
<target android:name="group_11">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="rotation"
android:startOffset="100"
android:duration="350"
android:valueFrom="-90"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="group_12">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="scaleX"
android:duration="550"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="550"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
</set>
</aapt:attr>
</target>
<target android:name="group_13">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="scaleX"
android:duration="550"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="550"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
</set>
</aapt:attr>
</target>
<target android:name="group_14">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="rotation"
android:startOffset="350"
android:duration="200"
android:valueFrom="5"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"/>
<objectAnimator
android:propertyName="rotation"
android:startOffset="250"
android:duration="100"
android:valueFrom="0"
android:valueTo="5"
android:valueType="floatType"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"/>
</set>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item >
<shape android:shape="rectangle">
<solid android:color="?attr/colorPrimaryContainer"/>
<corners android:radius="16dp"/>
</shape>
</item>
<item android:right="2dp" android:left="2dp" android:top="2dp" android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="?android:colorBackground"/>
<corners android:radius="16dp"/>
</shape>
</item>
</layer-list>

View File

@@ -1,23 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="70"
android:viewportHeight="70">
<group android:scaleX="0.73"
android:scaleY="0.73"
android:translateX="9.45"
android:translateY="9.45">
android:viewportWidth="768"
android:viewportHeight="768">
<group>
<clip-path
android:pathData="M128,384a256,255.96 0,1 0,512 0a256,255.96 0,1 0,-512 0z"/>
<path
android:pathData="M35,35m-32,0a32,32 0,1 1,64 0a32,32 0,1 1,-64 0"
android:strokeWidth="0.264583"
android:fillColor="#5a189a"/>
android:pathData="M128,128h512v511.96h-512z"
android:strokeWidth="0"
android:fillColor="#ff00f4"/>
<path
android:pathData="M35,35m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="0.264583"
android:fillColor="#7b2cbf"/>
android:pathData="m128,128v335.26c23.32,3.7 47.23,5.63 71.58,5.63 211.59,0 389.34,-144.9 439.43,-340.89H128Z"
android:strokeWidth="0"
android:fillColor="#7000b8"/>
<path
android:pathData="M35,35m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0"
android:strokeWidth="0.264583"
android:fillColor="#9d4edd"/>
android:pathData="M384,384m-172.26,0a172.26,172.26 0,1 1,344.52 0a172.26,172.26 0,1 1,-344.52 0"
android:strokeWidth="0"
android:fillColor="#d300e5"/>
<path
android:pathData="m384,211.74c-95.13,0 -172.26,77.12 -172.26,172.26 0,24.51 5.13,47.83 14.37,68.93 89.21,-7.3 172.93,-33.96 246.97,-75.77 24.85,-18.81 47.7,-40.12 68.18,-63.56 -26.92,-60.04 -87.2,-101.86 -157.25,-101.86Z"
android:strokeWidth="0"
android:fillColor="#9000d1"/>
<path
android:pathData="m539.28,128c-35.57,189.07 -201.56,332.12 -400.97,332.12 -3.45,0 -6.89,-0.06 -10.31,-0.14v5.75c40.23,10.46 82.43,16.05 125.93,16.05 155.6,0 294.55,-71.23 386.07,-182.84v-170.93h-100.72Z"
android:strokeWidth="0"
android:fillColor="#a800d9"/>
</group>
</vector>

View File

@@ -1,27 +1,22 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="70"
android:viewportHeight="70">
<group android:scaleX="0.73"
android:scaleY="0.73"
android:translateX="9.45"
android:translateY="9.45">
android:viewportWidth="768"
android:viewportHeight="768">
<group>
<clip-path
android:pathData="M128,384a256,255.96 0,1 0,512 0a256,255.96 0,1 0,-512 0z"/>
<path
android:pathData="m35.019,3a32,32 0,0 0,-31.999 32,32 32,0 0,0 7.101,20h24.898zM15.08,30.355 L15.572,31.28c0.018,0.196 -0.055,0.224 -0.219,0.084 -0.602,0.196 -1.213,0.35 -1.832,0.462v1.808h2.188v0.798h-0.738v5.128h-0.547v-5.128h-0.903v1.808c0,1.429 -0.328,2.564 -0.984,3.404l-0.41,-0.715 0.246,-0.336h-2.133v0.799h-0.547v-8.743h0.52c0.146,0.028 0.155,0.112 0.027,0.252v2.774h1.012v-3.195h0.437c0.146,0.028 0.155,0.112 0.027,0.252v2.942h1.039v0.672L11.716,34.348v0.336c0.401,0.336 0.72,0.659 0.957,0.967l-0.328,0.798c-0.164,-0.28 -0.374,-0.602 -0.629,-0.966v1.933h-0.465v-1.765c-0.201,0.532 -0.419,0.967 -0.656,1.303l-0.301,-0.672c0.383,-0.532 0.693,-1.177 0.93,-1.934h-0.984v3.447h2.324v0.504c0.273,-0.476 0.41,-1.177 0.41,-2.102v-5.296l0.52,0.21c0.62,-0.112 1.148,-0.365 1.586,-0.757zM18.716,30.734h0.547c0.219,0.028 0.246,0.14 0.082,0.336v2.648c0.893,0.392 1.796,0.925 2.707,1.597l-0.328,0.967c-0.966,-0.757 -1.759,-1.261 -2.379,-1.513v4.371L18.716,39.14ZM12.318,31.112 L12.81,31.322c0.073,0.084 0.055,0.154 -0.055,0.21 -0.109,0.588 -0.246,1.177 -0.41,1.765l-0.437,-0.252c0.182,-0.672 0.319,-1.317 0.41,-1.933zM10.786,31.239c0.146,0.56 0.246,1.176 0.301,1.849l-0.465,0.252c-0.091,-0.841 -0.192,-1.457 -0.301,-1.849zM26.291,31.28c0.273,0.588 0.538,1.331 0.793,2.228l-0.629,0.504c-0.255,-0.897 -0.52,-1.653 -0.793,-2.27zM28.587,31.491 L29.244,31.785c0.182,0.084 0.182,0.21 0,0.378 -0.219,2.27 -0.656,3.923 -1.313,4.96 -0.583,0.925 -1.376,1.639 -2.379,2.144l-0.492,-0.883c0.984,-0.42 1.741,-1.009 2.27,-1.765 0.656,-0.953 1.076,-2.662 1.258,-5.128zM24.568,31.869c0.273,0.673 0.547,1.485 0.82,2.438l-0.629,0.504c-0.237,-0.869 -0.501,-1.681 -0.793,-2.438z"
android:strokeWidth="0.264583"
android:fillColor="#10002b"/>
android:pathData="m44.26,128c0,46.25 37.49,83.74 83.74,83.74h256c95.13,0 172.26,77.12 172.26,172.26h0c0,95.13 -77.12,172.26 -172.26,172.26H128c-46.24,0 -83.72,37.47 -83.74,83.71h723.74V128H44.26Z"
android:strokeWidth="0"
android:fillColor="#1f1f30"/>
<path
android:pathData="m34.98,23v24a12,12 0,0 0,12 -12,12 12,0 0,0 -12,-12z"
android:strokeWidth="0.264583"
android:fillColor="#10002b"/>
android:pathData="m481.82,384h0c0,54.03 -43.8,97.82 -97.82,97.82H0v-195.64h384c54.02,0 97.82,43.8 97.82,97.82Z"
android:strokeWidth="0"
android:fillColor="#1f1f30"/>
<path
android:pathData="m34.98,67a32,32 0,0 0,32 -32,32 32,0 0,0 -32,-32v8a24,24 0,0 1,24 24,24 24,0 0,1 -24,24z"
android:strokeWidth="0.264583"
android:fillColor="#10002b"/>
<path
android:pathData="M35.019,59L13.88,59a32,32 0,0 0,21.139 8z"
android:strokeWidth="0.264583"
android:fillColor="#10002b"/>
android:pathData="m442,366.7l-76.02,-43.89c-13.32,-7.69 -29.96,1.92 -29.96,17.3v87.78c0,15.38 16.65,24.99 29.96,17.3l76.02,-43.89c13.32,-7.69 13.32,-26.91 0,-34.6Z"
android:strokeWidth="0"
android:fillColor="#efe7ff"/>
</group>
</vector>

View File

@@ -1,27 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="70"
android:viewportHeight="70">
<group android:scaleX="0.73"
android:scaleY="0.73"
android:translateX="9.45"
android:translateY="9.45">
<path
android:pathData="m35.019,3a32,32 0,0 0,-31.999 32,32 32,0 0,0 7.101,20h24.898zM15.08,30.355 L15.572,31.28c0.018,0.196 -0.055,0.224 -0.219,0.084 -0.602,0.196 -1.213,0.35 -1.832,0.462v1.808h2.188v0.798h-0.738v5.128h-0.547v-5.128h-0.903v1.808c0,1.429 -0.328,2.564 -0.984,3.404l-0.41,-0.715 0.246,-0.336h-2.133v0.799h-0.547v-8.743h0.52c0.146,0.028 0.155,0.112 0.027,0.252v2.774h1.012v-3.195h0.437c0.146,0.028 0.155,0.112 0.027,0.252v2.942h1.039v0.672L11.716,34.348v0.336c0.401,0.336 0.72,0.659 0.957,0.967l-0.328,0.798c-0.164,-0.28 -0.374,-0.602 -0.629,-0.966v1.933h-0.465v-1.765c-0.201,0.532 -0.419,0.967 -0.656,1.303l-0.301,-0.672c0.383,-0.532 0.693,-1.177 0.93,-1.934h-0.984v3.447h2.324v0.504c0.273,-0.476 0.41,-1.177 0.41,-2.102v-5.296l0.52,0.21c0.62,-0.112 1.148,-0.365 1.586,-0.757zM18.716,30.734h0.547c0.219,0.028 0.246,0.14 0.082,0.336v2.648c0.893,0.392 1.796,0.925 2.707,1.597l-0.328,0.967c-0.966,-0.757 -1.759,-1.261 -2.379,-1.513v4.371L18.716,39.14ZM12.318,31.112 L12.81,31.322c0.073,0.084 0.055,0.154 -0.055,0.21 -0.109,0.588 -0.246,1.177 -0.41,1.765l-0.437,-0.252c0.182,-0.672 0.319,-1.317 0.41,-1.933zM10.786,31.239c0.146,0.56 0.246,1.176 0.301,1.849l-0.465,0.252c-0.091,-0.841 -0.192,-1.457 -0.301,-1.849zM26.291,31.28c0.273,0.588 0.538,1.331 0.793,2.228l-0.629,0.504c-0.255,-0.897 -0.52,-1.653 -0.793,-2.27zM28.587,31.491 L29.244,31.785c0.182,0.084 0.182,0.21 0,0.378 -0.219,2.27 -0.656,3.923 -1.313,4.96 -0.583,0.925 -1.376,1.639 -2.379,2.144l-0.492,-0.883c0.984,-0.42 1.741,-1.009 2.27,-1.765 0.656,-0.953 1.076,-2.662 1.258,-5.128zM24.568,31.869c0.273,0.673 0.547,1.485 0.82,2.438l-0.629,0.504c-0.237,-0.869 -0.501,-1.681 -0.793,-2.438z"
android:strokeWidth="0.264583"
android:fillColor="#000000"/>
<path
android:pathData="m34.98,23v24a12,12 0,0 0,12 -12,12 12,0 0,0 -12,-12z"
android:strokeWidth="0.264583"
android:fillColor="#000000"/>
<path
android:pathData="m34.98,67a32,32 0,0 0,32 -32,32 32,0 0,0 -32,-32v8a24,24 0,0 1,24 24,24 24,0 0,1 -24,24z"
android:strokeWidth="0.264583"
android:fillColor="#000000"/>
<path
android:pathData="M35.019,59L13.88,59a32,32 0,0 0,21.139 8z"
android:strokeWidth="0.264583"
android:fillColor="#000000"/>
</group>
android:width="768dp"
android:height="768dp"
android:viewportWidth="768"
android:viewportHeight="768">
<group>
<clip-path
android:pathData="M128,384a256,255.96 0,1 0,512 0a256,255.96 0,1 0,-512 0z"/>
<path
android:pathData="M384,122.15A270.94,270.94 0,0 0,331.21 128L439.74,128A270.94,270.94 0,0 0,384 122.15zM183.16,211.74A270.94,270.94 0,0 0,135.74 286.18L384,286.18C438.02,286.18 481.82,329.98 481.82,384C481.82,438.03 438.02,481.82 384,481.82L128.98,481.82A270.94,270.94 0,0 0,168.56 556.26L384,556.26C479.14,556.26 556.26,479.13 556.26,384C556.26,288.86 479.13,211.74 384,211.74L183.16,211.74zM272.59,639.97A270.94,270.94 0,0 0,384 664.03A270.94,270.94 0,0 0,495.41 639.97L272.59,639.97z"
android:fillColor="#000000"/>
<path
android:pathData="m442,366.7l-76.02,-43.89c-13.32,-7.69 -29.96,1.92 -29.96,17.3v87.78c0,15.38 16.65,24.99 29.96,17.3l76.02,-43.89c13.32,-7.69 13.32,-26.91 0,-34.6Z"
android:strokeWidth="0"
android:fillColor="#000000"/>
</group>
</vector>

View File

@@ -51,13 +51,9 @@
android:text="@string/extensions"
android:textSize="28sp" />
<ImageView
android:id="@+id/settingsLogo"
<Space
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="bottom"
app:srcCompat="@drawable/anim_splash"
tools:ignore="ContentDescription" />
android:layout_height="80dp" />
</LinearLayout>
@@ -69,13 +65,38 @@
tools:ignore="UseCompoundDrawables">
</LinearLayout>
<SearchView
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/searchView"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="0dp"
android:layoutDirection="ltr" />
android:layout_height="56dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:transitionName="@string/search"
app:boxBackgroundColor="@color/bg"
app:boxBackgroundMode="outline"
app:boxCornerRadiusBottomEnd="28dp"
app:boxCornerRadiusBottomStart="28dp"
app:boxCornerRadiusTopEnd="28dp"
app:boxCornerRadiusTopStart="28dp"
app:endIconDrawable="@drawable/ic_round_search_24"
app:hintAnimationEnabled="true">
<AutoCompleteTextView
android:id="@+id/searchViewText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="@font/poppins_bold"
android:imeOptions="actionSearch"
android:inputType="textPersonName"
android:selectAllOnFocus="true"
android:padding="8dp"
android:textSize="14sp"
app:boxStrokeColor="@color/text_input_layout_stroke_color"
tools:ignore="LabelFor,TextContrastCheck" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
@@ -84,15 +105,26 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabTextColor="?attr/colorOnBackground"
selectedTabIndicatorColor="?attr/colorPrimary"
app:tabIndicatorColor="?attr/colorPrimary"
app:tabGravity="fill">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Anime"/>
android:text="Installed Anime"/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Manga"/>
android:text="Available Anime"/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Installed Manga"/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Available Manga"/>
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2

View File

@@ -4,7 +4,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".media.user.ListActivity">
tools:context=".media.user.ListActivity"
android:fitsSystemWindows="true">
<ProgressBar
android:id="@+id/listProgressBar"

View File

@@ -41,13 +41,13 @@
app:abb_animationDuration="300"
app:abb_animationInterpolator="@anim/over_shoot"
app:abb_badgeBackgroundColor="#F44336"
app:abb_indicatorColor="?attr/colorSecondary"
app:abb_indicatorColor="?attr/colorOnPrimaryContainer"
app:abb_indicatorLocation="bottom"
app:abb_indicatorMargin="28dp"
app:abb_selectedTabType="text"
app:abb_tabColor="?attr/colorSecondary"
app:abb_tabColorDisabled="?attr/colorSecondaryContainer"
app:abb_tabColorSelected="?attr/colorPrimary"
app:abb_tabColor="?attr/colorOnPrimary"
app:abb_tabColorDisabled="?attr/colorOnSecondary"
app:abb_tabColorSelected="?attr/colorOnPrimaryContainer"
app:abb_tabs="@menu/bottom_navbar_menu"
app:abb_textAppearance="@style/NavBarText"
tools:visibility="visible" />

View File

@@ -55,7 +55,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:cardBackgroundColor="#000000"
app:cardBackgroundColor="?attr/colorSurface"
app:cardCornerRadius="16dp"
app:contentPadding="8dp"
app:strokeColor="?attr/colorSecondary"
@@ -70,7 +70,7 @@
android:layout_marginEnd="8dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/app_name"
android:textColor="?android:colorBackground"
android:textColor="?attr/colorOnSurface"
android:textSize="16sp" />
</com.google.android.material.card.MaterialCardView>
@@ -93,7 +93,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
app:cardBackgroundColor="#000000"
app:cardBackgroundColor="?attr/colorSurface"
app:cardCornerRadius="16dp"
app:contentPadding="8dp"
app:strokeColor="?attr/colorSecondary"
@@ -108,7 +108,7 @@
android:layout_marginEnd="8dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/app_name"
android:textColor="?android:colorBackground"
android:textColor="?attr/colorOnSurface"
android:textSize="16sp" />
</com.google.android.material.card.MaterialCardView>
@@ -133,7 +133,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardBackgroundColor="#000000"
app:cardBackgroundColor="?attr/colorSurface"
app:cardCornerRadius="16dp"
app:contentPadding="8dp"
app:strokeColor="?attr/colorSecondary"
@@ -148,7 +148,7 @@
android:layout_marginEnd="8dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/app_name"
android:textColor="?android:colorBackground"
android:textColor="?attr/colorOnSurface"
android:textSize="16sp" />
</com.google.android.material.card.MaterialCardView>
@@ -170,7 +170,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardBackgroundColor="#000000"
app:cardBackgroundColor="?attr/colorSurface"
app:cardCornerRadius="16dp"
app:contentPadding="8dp"
app:strokeColor="?attr/colorSecondary"
@@ -185,7 +185,7 @@
android:layout_marginEnd="8dp"
android:fontFamily="@font/poppins_bold"
android:text="@string/app_name"
android:textColor="?android:colorBackground"
android:textColor="?attr/colorOnSurface"
android:textSize="16sp" />
</com.google.android.material.card.MaterialCardView>
@@ -268,7 +268,11 @@
android:layout_marginEnd="48dp"
android:fontFamily="@font/poppins"
android:singleLine="false"
android:textColor="?android:colorBackground"
android:textColor="@color/bg_white"
android:shadowColor="#000"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="1"
android:textSize="12sp"
tools:ignore="TextContrastCheck"
tools:text="@string/popular_anime" />

View File

@@ -123,6 +123,7 @@
android:text="@string/add"
android:textAllCaps="true"
android:textColor="?attr/colorPrimary"
app:strokeColor="?attr/colorPrimary"
android:textSize="14sp"
android:textStyle="bold"
app:cornerRadius="16dp"
@@ -242,14 +243,14 @@
android:layout_height="wrap_content"
android:padding="0dp"
android:layout_gravity="bottom"
android:background="?attr/colorPrimaryContainer"
android:background="?attr/colorSurface"
android:translationZ="1dp"
app:itemActiveIndicatorStyle="@style/BottomNavBar"
app:itemIconTint="@color/tab_layout_icon"
app:itemRippleColor="?attr/colorSecondary"
app:itemRippleColor="?attr/colorPrimary"
app:itemTextAppearanceActive="@style/NavBarText"
app:itemTextAppearanceInactive="@style/NavBarText"
app:itemTextColor="?attr/colorOnPrimaryContainer"
app:itemTextColor="@color/tab_layout_icon"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" />
<androidx.cardview.widget.CardView

View File

@@ -161,16 +161,34 @@
</LinearLayout>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/settingsUseMaterialYou"
android:id="@+id/settingsUseMaterialYou"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:drawableStart="@drawable/ic_round_new_releases_24"
android:drawablePadding="16dp"
android:elegantTextHeight="true"
android:fontFamily="@font/poppins_bold"
android:minHeight="64dp"
android:text="@string/use_material_you"
android:textAlignment="viewStart"
android:textColor="?attr/colorOnBackground"
app:cornerRadius="0dp"
app:drawableTint="?attr/colorPrimary"
app:showText="false"
app:thumbTint="@color/button_switch_track" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/settingsUseOLED"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:drawableStart="@drawable/ic_round_new_releases_24"
android:drawableStart="@drawable/ic_round_brightness_4_24"
android:drawablePadding="16dp"
android:elegantTextHeight="true"
android:fontFamily="@font/poppins_bold"
android:minHeight="64dp"
android:text="@string/use_material_you"
android:text="Use OLED theme variant"
android:textAlignment="viewStart"
android:textColor="?attr/colorOnBackground"
app:cornerRadius="0dp"

View File

@@ -248,7 +248,8 @@
android:valueTo="10"
app:labelBehavior="gone"
app:thumbElevation="0dp"
app:trackColorInactive="?attr/colorSecondary"
app:trackColorInactive="?attr/colorOnSecondary"
app:trackColorActive="?attr/colorSecondary"
app:trackHeight="24dp" />
<ImageView
@@ -290,7 +291,8 @@
android:valueTo="10"
app:labelBehavior="gone"
app:thumbElevation="0dp"
app:trackColorInactive="?attr/colorSecondary"
app:trackColorInactive="?attr/colorOnSecondary"
app:trackColorActive="?attr/colorSecondary"
app:trackHeight="24dp" />
<ImageView

View File

@@ -1,34 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="32dp"
android:paddingEnd="32dp">
<LinearLayout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/allAnimeExtensionsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="32dp"
android:paddingEnd="32dp">
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/animeExtensionsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="All Extensions"
android:textSize="28sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/allAnimeExtensionsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@@ -41,12 +41,13 @@
android:layout_height="64dp"
android:layout_gravity="bottom|center_horizontal"
android:layout_margin="32dp"
android:backgroundTint="?attr/colorPrimaryContainer"
android:fontFamily="@font/poppins_bold"
android:text="@string/login"
android:textColor="?attr/colorOnPrimary"
android:textColor="?attr/colorOnPrimaryContainer"
app:cornerRadius="16dp"
app:icon="@drawable/ic_anilist"
app:iconTint="@color/button_icon" />
app:iconTint="?attr/colorOnPrimaryContainer" />
<LinearLayout
android:layout_width="wrap_content"

View File

@@ -1,35 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="32dp"
android:paddingEnd="32dp">
<LinearLayout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/allMangaExtensionsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="32dp"
android:paddingEnd="32dp">
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mangaExtensionsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="All Extensions"
android:textSize="28sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/allMangaExtensionsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@@ -60,10 +60,12 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.card.MaterialCardView
android:id="@+id/animeUserAvatarContainer"
android:layout_width="52dp"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:backgroundTint="?attr/colorPrimaryContainer"
app:strokeColor="@color/text_input_layout_stroke_color"
app:cardCornerRadius="26dp">
<com.google.android.material.imageview.ShapeableImageView

View File

@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardBackgroundColor="?android:colorBackground"
android:background="@drawable/card_outline"
app:cardCornerRadius="12dp">
<LinearLayout

View File

@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_margin="8dp"
app:cardBackgroundColor="?android:colorBackground"
android:background="@drawable/card_outline"
app:cardCornerRadius="16dp">
<LinearLayout

View File

@@ -8,7 +8,7 @@
android:layout_margin="8dp"
android:clipToPadding="false"
android:translationZ="8dp"
app:cardBackgroundColor="?android:colorBackground"
android:background="@drawable/card_outline"
app:cardCornerRadius="16dp"
app:cardElevation="4dp">

View File

@@ -8,7 +8,7 @@
android:layout_margin="8dp"
android:backgroundTintMode="src_atop"
android:longClickable="true"
app:cardBackgroundColor="?attr/colorSurface"
android:background="@drawable/card_outline"
app:cardCornerRadius="16dp">
<View

View File

@@ -62,10 +62,12 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.card.MaterialCardView
android:id="@+id/mangaUserAvatarContainer"
android:layout_width="52dp"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:backgroundTint="?attr/colorPrimaryContainer"
app:strokeColor="@color/text_input_layout_stroke_color"
app:cardCornerRadius="26dp">
<com.google.android.material.imageview.ShapeableImageView

View File

@@ -55,7 +55,7 @@
android:layout_marginStart="2dp"
android:fontFamily="@font/poppins_bold"
android:paddingTop="2dp"
android:textColor="@color/bg_white"
android:textColor="?attr/colorOnPrimary"
android:textSize="12sp"
tools:ignore="TextContrastCheck"
tools:text="0.0" />
@@ -65,6 +65,7 @@
android:layout_width="12dp"
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_round_star_24"
app:tint="?attr/colorOnPrimary"
tools:ignore="ContentDescription" />
</LinearLayout>

View File

@@ -74,7 +74,7 @@
android:layout_marginStart="2dp"
android:fontFamily="@font/poppins_bold"
android:paddingTop="2dp"
android:textColor="@color/bg_white"
android:textColor="?attr/colorOnPrimary"
android:textSize="12sp"
tools:ignore="TextContrastCheck"
tools:text="0.0" />
@@ -84,6 +84,7 @@
android:layout_width="12dp"
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_round_star_24"
app:tint="?attr/colorOnPrimary"
tools:ignore="ContentDescription" />
</LinearLayout>

View File

@@ -72,7 +72,7 @@
android:layout_marginStart="2dp"
android:fontFamily="@font/poppins_bold"
android:paddingTop="2dp"
android:textColor="@color/bg_white"
android:textColor="?attr/colorOnPrimary"
android:textSize="12sp"
tools:ignore="TextContrastCheck"
tools:text="0.0" />
@@ -82,6 +82,7 @@
android:layout_width="12dp"
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_round_star_24"
app:tint="?attr/colorOnPrimary"
tools:ignore="ContentDescription" />
</LinearLayout>

View File

@@ -92,7 +92,7 @@
android:layout_marginStart="2dp"
android:fontFamily="@font/poppins_bold"
android:paddingTop="2dp"
android:textColor="@color/bg_white"
android:textColor="?attr/colorOnPrimary"
android:textSize="12sp"
tools:ignore="TextContrastCheck"
tools:text="0.0" />
@@ -102,6 +102,7 @@
android:layout_width="12dp"
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_round_star_24"
app:tint="?attr/colorOnPrimary"
tools:ignore="ContentDescription" />
</LinearLayout>

View File

@@ -60,6 +60,8 @@
android:layout_weight="1"
android:layoutDirection="inherit"
android:text="@string/list_only"
android:textColor="?attr/colorOnBackground"
app:buttonTint="?attr/colorPrimary"
android:visibility="visible"
app:checkedState="indeterminate"
tools:ignore="TextContrastCheck,TouchTargetSizeCheck" />
@@ -75,7 +77,8 @@
android:text="@string/adult"
android:textAlignment="textEnd"
android:visibility="visible"
app:buttonTint="?attr/colorPrimaryContainer"
android:textColor="?attr/colorOnBackground"
app:buttonTint="?attr/colorPrimary"
tools:ignore="TextContrastCheck,TouchTargetSizeCheck" />
</LinearLayout>

View File

@@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:colorBackground">
android:background="@color/bg_black">
<ImageView
android:id="@+id/splashImage"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -143,11 +143,105 @@
<item name="colorOnBackground">@color/bg_white</item>
<item name="colorSurface">@color/bg_black</item>
<item name="colorOnSurface">@color/bg_white</item>
<item name="colorSurfaceVariant">@color/bg_white</item>
<item name="colorOnSurfaceVariant">@color/bg_black</item>
<item name="colorOutline">@color/bg_white</item>
<item name="colorOnSurfaceInverse">@color/bg_black</item>
<item name="colorSurfaceInverse">@color/bg_white</item>
<item name="colorSurfaceVariant">@color/bg_black</item>
<item name="colorOnSurfaceVariant">@color/bg_white</item>
<item name="colorOutline">@color/bg_black</item>
<item name="colorOnSurfaceInverse">@color/bg_white</item>
<item name="colorSurfaceInverse">@color/bg_black</item>
<item name="colorPrimaryInverse">@color/bg_black</item>
</style>
<style name="Theme.Dantotsu.Red" parent="Theme.Base">
<item name="colorPrimary">@color/md_0_theme_dark_primary</item>
<item name="colorOnPrimary">@color/md_0_theme_dark_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_0_theme_dark_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_0_theme_dark_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_0_theme_dark_secondary</item>
<item name="colorOnSecondary">@color/md_0_theme_dark_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_0_theme_dark_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_0_theme_dark_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_0_theme_dark_tertiary</item>
<item name="colorOnTertiary">@color/md_0_theme_dark_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_0_theme_dark_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_0_theme_dark_onTertiaryContainer</item>
<item name="colorError">@color/md_0_theme_dark_error</item>
<item name="colorErrorContainer">@color/md_0_theme_dark_errorContainer</item>
<item name="colorOnError">@color/md_0_theme_dark_onError</item>
<item name="colorOnErrorContainer">@color/md_0_theme_dark_onErrorContainer</item>
<item name="android:colorBackground">@color/md_0_theme_dark_background</item>
<item name="colorOnBackground">@color/md_0_theme_dark_onBackground</item>
<item name="colorSurface">@color/md_0_theme_dark_surface</item>
<item name="colorOnSurface">@color/md_0_theme_dark_onSurface</item>
<item name="colorSurfaceVariant">@color/md_0_theme_dark_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_0_theme_dark_onSurfaceVariant</item>
<item name="colorOutline">@color/md_0_theme_dark_outline</item>
<item name="colorOnSurfaceInverse">@color/md_0_theme_dark_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_0_theme_dark_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_0_theme_dark_inversePrimary</item>
</style>
<style name="Theme.Dantotsu.Lavender" parent="Theme.Base">
<item name="colorPrimary">@color/md_1_theme_dark_primary</item>
<item name="colorOnPrimary">@color/md_1_theme_dark_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_1_theme_dark_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_1_theme_dark_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_1_theme_dark_secondary</item>
<item name="colorOnSecondary">@color/md_1_theme_dark_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_1_theme_dark_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_1_theme_dark_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_1_theme_dark_tertiary</item>
<item name="colorOnTertiary">@color/md_1_theme_dark_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_1_theme_dark_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_1_theme_dark_onTertiaryContainer</item>
<item name="colorError">@color/md_1_theme_dark_error</item>
<item name="colorErrorContainer">@color/md_1_theme_dark_errorContainer</item>
<item name="colorOnError">@color/md_1_theme_dark_onError</item>
<item name="colorOnErrorContainer">@color/md_1_theme_dark_onErrorContainer</item>
<item name="android:colorBackground">@color/md_1_theme_dark_background</item>
<item name="colorOnBackground">@color/md_1_theme_dark_onBackground</item>
<item name="colorSurface">@color/md_1_theme_dark_surface</item>
<item name="colorOnSurface">@color/md_1_theme_dark_onSurface</item>
<item name="colorSurfaceVariant">@color/md_1_theme_dark_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_1_theme_dark_onSurfaceVariant</item>
<item name="colorOutline">@color/md_1_theme_dark_outline</item>
<item name="colorOnSurfaceInverse">@color/md_1_theme_dark_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_1_theme_dark_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_1_theme_dark_inversePrimary</item>
</style>
<style name="Theme.Dantotsu.BlueOLED" parent="Theme.Dantotsu.Blue">
<item name="android:colorBackground">@color/darkest_Black</item>
<item name="colorSurface">@color/darkest_Black</item>
</style>
<style name="Theme.Dantotsu.GreenOLED" parent="Theme.Dantotsu.Green">
<item name="android:colorBackground">@color/darkest_Black</item>
<item name="colorSurface">@color/darkest_Black</item>
</style>
<style name="Theme.Dantotsu.PurpleOLED" parent="Theme.Dantotsu.Purple">
<item name="android:colorBackground">@color/darkest_Black</item>
<item name="colorSurface">@color/darkest_Black</item>
</style>
<style name="Theme.Dantotsu.PinkOLED" parent="Theme.Dantotsu.Pink">
<item name="android:colorBackground">@color/darkest_Black</item>
<item name="colorSurface">@color/darkest_Black</item>
</style>
<style name="Theme.Dantotsu.MonochromeOLED" parent="Theme.Dantotsu.Monochrome">
<item name="android:colorBackground">@color/darkest_Black</item>
<item name="colorSurface">@color/darkest_Black</item>
</style>
<style name="Theme.Dantotsu.RedOLED" parent="Theme.Dantotsu.Red">
<item name="android:colorBackground">@color/darkest_Black</item>
<item name="colorSurface">@color/darkest_Black</item>
</style>
<style name="Theme.Dantotsu.LavenderOLED" parent="Theme.Dantotsu.Lavender">
<item name="android:colorBackground">@color/darkest_Black</item>
<item name="colorSurface">@color/darkest_Black</item>
</style>
</resources>

View File

@@ -20,6 +20,7 @@
<color name="warning">#FF0000</color>
<color name="grey_20">#444444</color>
<color name="grey_60">#999999</color>
<color name="darkest_Black">#030201</color>
<!-- theme 1 -->
<color name="seed_1">#00658e</color>
@@ -269,4 +270,132 @@
<color name="md_theme_dark_4_surfaceTint">#FFAED9</color>
<color name="md_theme_dark_4_outlineVariant">#504349</color>
<color name="md_theme_dark_4_scrim">#000000</color>
<color name="seed_5">#c9000b</color>
<color name="md_0_theme_light_primary">#C0000A</color>
<color name="md_0_theme_light_onPrimary">#FFFFFF</color>
<color name="md_0_theme_light_primaryContainer">#FFDAD5</color>
<color name="md_0_theme_light_onPrimaryContainer">#410001</color>
<color name="md_0_theme_light_secondary">#775652</color>
<color name="md_0_theme_light_onSecondary">#FFFFFF</color>
<color name="md_0_theme_light_secondaryContainer">#FFDAD5</color>
<color name="md_0_theme_light_onSecondaryContainer">#2C1512</color>
<color name="md_0_theme_light_tertiary">#705C2E</color>
<color name="md_0_theme_light_onTertiary">#FFFFFF</color>
<color name="md_0_theme_light_tertiaryContainer">#FCDFA6</color>
<color name="md_0_theme_light_onTertiaryContainer">#261A00</color>
<color name="md_0_theme_light_error">#BA1A1A</color>
<color name="md_0_theme_light_errorContainer">#FFDAD6</color>
<color name="md_0_theme_light_onError">#FFFFFF</color>
<color name="md_0_theme_light_onErrorContainer">#410002</color>
<color name="md_0_theme_light_background">#FFFBFF</color>
<color name="md_0_theme_light_onBackground">#201A19</color>
<color name="md_0_theme_light_surface">#FFFBFF</color>
<color name="md_0_theme_light_onSurface">#201A19</color>
<color name="md_0_theme_light_surfaceVariant">#F5DDDA</color>
<color name="md_0_theme_light_onSurfaceVariant">#534341</color>
<color name="md_0_theme_light_outline">#857370</color>
<color name="md_0_theme_light_inverseOnSurface">#FBEEEC</color>
<color name="md_0_theme_light_inverseSurface">#362F2E</color>
<color name="md_0_theme_light_inversePrimary">#FFB4AA</color>
<color name="md_0_theme_light_shadow">#000000</color>
<color name="md_0_theme_light_surfaceTint">#C0000A</color>
<color name="md_0_theme_light_outlineVariant">#D8C2BE</color>
<color name="md_0_theme_light_scrim">#000000</color>
<color name="md_0_theme_dark_primary">#FFB4AA</color>
<color name="md_0_theme_dark_onPrimary">#690003</color>
<color name="md_0_theme_dark_primaryContainer">#930005</color>
<color name="md_0_theme_dark_onPrimaryContainer">#FFDAD5</color>
<color name="md_0_theme_dark_secondary">#E7BDB7</color>
<color name="md_0_theme_dark_onSecondary">#442926</color>
<color name="md_0_theme_dark_secondaryContainer">#5D3F3B</color>
<color name="md_0_theme_dark_onSecondaryContainer">#FFDAD5</color>
<color name="md_0_theme_dark_tertiary">#DFC38C</color>
<color name="md_0_theme_dark_onTertiary">#3E2E04</color>
<color name="md_0_theme_dark_tertiaryContainer">#574419</color>
<color name="md_0_theme_dark_onTertiaryContainer">#FCDFA6</color>
<color name="md_0_theme_dark_error">#FFB4AB</color>
<color name="md_0_theme_dark_errorContainer">#93000A</color>
<color name="md_0_theme_dark_onError">#690005</color>
<color name="md_0_theme_dark_onErrorContainer">#FFDAD6</color>
<color name="md_0_theme_dark_background">#201A19</color>
<color name="md_0_theme_dark_onBackground">#EDE0DE</color>
<color name="md_0_theme_dark_surface">#201A19</color>
<color name="md_0_theme_dark_onSurface">#EDE0DE</color>
<color name="md_0_theme_dark_surfaceVariant">#534341</color>
<color name="md_0_theme_dark_onSurfaceVariant">#D8C2BE</color>
<color name="md_0_theme_dark_outline">#A08C89</color>
<color name="md_0_theme_dark_inverseOnSurface">#201A19</color>
<color name="md_0_theme_dark_inverseSurface">#EDE0DE</color>
<color name="md_0_theme_dark_inversePrimary">#C0000A</color>
<color name="md_0_theme_dark_shadow">#000000</color>
<color name="md_0_theme_dark_surfaceTint">#FFB4AA</color>
<color name="md_0_theme_dark_outlineVariant">#534341</color>
<color name="md_0_theme_dark_scrim">#000000</color>
<color name="seed_6">#6750A4</color>
<color name="md_1_theme_light_primary">#6750A4</color>
<color name="md_1_theme_light_onPrimary">#FFFFFF</color>
<color name="md_1_theme_light_primaryContainer">#E9DDFF</color>
<color name="md_1_theme_light_onPrimaryContainer">#22005D</color>
<color name="md_1_theme_light_secondary">#625B71</color>
<color name="md_1_theme_light_onSecondary">#FFFFFF</color>
<color name="md_1_theme_light_secondaryContainer">#E8DEF8</color>
<color name="md_1_theme_light_onSecondaryContainer">#1E192B</color>
<color name="md_1_theme_light_tertiary">#7E5260</color>
<color name="md_1_theme_light_onTertiary">#FFFFFF</color>
<color name="md_1_theme_light_tertiaryContainer">#FFD9E3</color>
<color name="md_1_theme_light_onTertiaryContainer">#31101D</color>
<color name="md_1_theme_light_error">#BA1A1A</color>
<color name="md_1_theme_light_errorContainer">#FFDAD6</color>
<color name="md_1_theme_light_onError">#FFFFFF</color>
<color name="md_1_theme_light_onErrorContainer">#410002</color>
<color name="md_1_theme_light_background">#FFFBFF</color>
<color name="md_1_theme_light_onBackground">#1C1B1E</color>
<color name="md_1_theme_light_surface">#FFFBFF</color>
<color name="md_1_theme_light_onSurface">#1C1B1E</color>
<color name="md_1_theme_light_surfaceVariant">#E7E0EB</color>
<color name="md_1_theme_light_onSurfaceVariant">#49454E</color>
<color name="md_1_theme_light_outline">#7A757F</color>
<color name="md_1_theme_light_inverseOnSurface">#F4EFF4</color>
<color name="md_1_theme_light_inverseSurface">#313033</color>
<color name="md_1_theme_light_inversePrimary">#CFBCFF</color>
<color name="md_1_theme_light_shadow">#000000</color>
<color name="md_1_theme_light_surfaceTint">#6750A4</color>
<color name="md_1_theme_light_outlineVariant">#CAC4CF</color>
<color name="md_1_theme_light_scrim">#000000</color>
<color name="md_1_theme_dark_primary">#CFBCFF</color>
<color name="md_1_theme_dark_onPrimary">#381E72</color>
<color name="md_1_theme_dark_primaryContainer">#4F378A</color>
<color name="md_1_theme_dark_onPrimaryContainer">#E9DDFF</color>
<color name="md_1_theme_dark_secondary">#CBC2DB</color>
<color name="md_1_theme_dark_onSecondary">#332D41</color>
<color name="md_1_theme_dark_secondaryContainer">#4A4458</color>
<color name="md_1_theme_dark_onSecondaryContainer">#E8DEF8</color>
<color name="md_1_theme_dark_tertiary">#EFB8C8</color>
<color name="md_1_theme_dark_onTertiary">#4A2532</color>
<color name="md_1_theme_dark_tertiaryContainer">#633B48</color>
<color name="md_1_theme_dark_onTertiaryContainer">#FFD9E3</color>
<color name="md_1_theme_dark_error">#FFB4AB</color>
<color name="md_1_theme_dark_errorContainer">#93000A</color>
<color name="md_1_theme_dark_onError">#690005</color>
<color name="md_1_theme_dark_onErrorContainer">#FFDAD6</color>
<color name="md_1_theme_dark_background">#1C1B1E</color>
<color name="md_1_theme_dark_onBackground">#E6E1E6</color>
<color name="md_1_theme_dark_surface">#1C1B1E</color>
<color name="md_1_theme_dark_onSurface">#E6E1E6</color>
<color name="md_1_theme_dark_surfaceVariant">#49454E</color>
<color name="md_1_theme_dark_onSurfaceVariant">#CAC4CF</color>
<color name="md_1_theme_dark_outline">#948F99</color>
<color name="md_1_theme_dark_inverseOnSurface">#1C1B1E</color>
<color name="md_1_theme_dark_inverseSurface">#E6E1E6</color>
<color name="md_1_theme_dark_inversePrimary">#6750A4</color>
<color name="md_1_theme_dark_shadow">#000000</color>
<color name="md_1_theme_dark_surfaceTint">#CFBCFF</color>
<color name="md_1_theme_dark_outlineVariant">#49454E</color>
<color name="md_1_theme_dark_scrim">#000000</color>
<color name="CustomColor1">#93DB00</color>
<color name="CustomColor2">#68AF86</color>
<color name="CustomColor3">#0096AE</color>
<color name="CustomColor4">#000000</color>
</resources>

View File

@@ -53,5 +53,8 @@
<item name="android:popupBackground">?android:colorBackground</item>
</style>
<style name="BottomNavBar" parent="Widget.Material3.BottomNavigationView.ActiveIndicator"/>
<style name="BottomNavBar" parent="">
<!-- set background color to transparent -->
<item name="android:background">@android:color/transparent</item>
</style>
</resources>

View File

@@ -1,7 +1,7 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Base" parent="Theme.Material3.DayNight">
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">?android:colorBackground</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="elevationOverlayEnabled">false</item>
<item name="windowActionBar">false</item>
@@ -15,6 +15,8 @@
<item name="snackbarButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Snackbar</item>
<item name="snackbarTextViewStyle">@string/MySnackBarText</item>
<item name="popupMenuStyle">@style/MyPopup</item>
<item name="android:windowSplashScreenAnimationDuration" tools:targetApi="s">1000</item>
<item name="android:windowSplashScreenAnimatedIcon" tools:targetApi="s">@drawable/anim_splash</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
</style>
@@ -190,13 +192,13 @@
</style>
<style name="Theme.Dantotsu.Monochrome" parent="Theme.Base">
<item name="colorPrimary">@color/grey_20</item>
<item name="colorPrimary">@color/bg_black</item>
<item name="colorOnPrimary">@color/bg_white</item>
<item name="colorPrimaryContainer">@color/bg_black</item>
<item name="colorOnPrimaryContainer">@color/bg_white</item>
<item name="colorSecondary">@color/bg_black</item>
<item name="colorOnSecondary">@color/bg_white</item>
<item name="colorSecondaryContainer">@color/grey_60</item>
<item name="colorSecondaryContainer">@color/bg_black</item>
<item name="colorOnSecondaryContainer">@color/bg_white</item>
<item name="colorTertiary">@color/bg_black</item>
<item name="colorOnTertiary">@color/bg_white</item>
@@ -218,5 +220,62 @@
<item name="colorPrimaryInverse">@color/bg_white</item>
</style>
<style name="Theme.Dantotsu.Red" parent="Theme.Base">
<item name="colorPrimary">@color/md_0_theme_light_primary</item>
<item name="colorOnPrimary">@color/md_0_theme_light_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_0_theme_light_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_0_theme_light_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_0_theme_light_secondary</item>
<item name="colorOnSecondary">@color/md_0_theme_light_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_0_theme_light_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_0_theme_light_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_0_theme_light_tertiary</item>
<item name="colorOnTertiary">@color/md_0_theme_light_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_0_theme_light_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_0_theme_light_onTertiaryContainer</item>
<item name="colorError">@color/md_0_theme_light_error</item>
<item name="colorErrorContainer">@color/md_0_theme_light_errorContainer</item>
<item name="colorOnError">@color/md_0_theme_light_onError</item>
<item name="colorOnErrorContainer">@color/md_0_theme_light_onErrorContainer</item>
<item name="android:colorBackground">@color/md_0_theme_light_background</item>
<item name="colorOnBackground">@color/md_0_theme_light_onBackground</item>
<item name="colorSurface">@color/md_0_theme_light_surface</item>
<item name="colorOnSurface">@color/md_0_theme_light_onSurface</item>
<item name="colorSurfaceVariant">@color/md_0_theme_light_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_0_theme_light_onSurfaceVariant</item>
<item name="colorOutline">@color/md_0_theme_light_outline</item>
<item name="colorOnSurfaceInverse">@color/md_0_theme_light_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_0_theme_light_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_0_theme_light_inversePrimary</item>
</style>
<style name="Theme.Dantotsu.Lavender" parent="Theme.Base">
<item name="colorPrimary">@color/md_1_theme_light_primary</item>
<item name="colorOnPrimary">@color/md_1_theme_light_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_1_theme_light_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_1_theme_light_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_1_theme_light_secondary</item>
<item name="colorOnSecondary">@color/md_1_theme_light_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_1_theme_light_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_1_theme_light_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_1_theme_light_tertiary</item>
<item name="colorOnTertiary">@color/md_1_theme_light_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_1_theme_light_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_1_theme_light_onTertiaryContainer</item>
<item name="colorError">@color/md_1_theme_light_error</item>
<item name="colorErrorContainer">@color/md_1_theme_light_errorContainer</item>
<item name="colorOnError">@color/md_1_theme_light_onError</item>
<item name="colorOnErrorContainer">@color/md_1_theme_light_onErrorContainer</item>
<item name="android:colorBackground">@color/md_1_theme_light_background</item>
<item name="colorOnBackground">@color/md_1_theme_light_onBackground</item>
<item name="colorSurface">@color/md_1_theme_light_surface</item>
<item name="colorOnSurface">@color/md_1_theme_light_onSurface</item>
<item name="colorSurfaceVariant">@color/md_1_theme_light_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_1_theme_light_onSurfaceVariant</item>
<item name="colorOutline">@color/md_1_theme_light_outline</item>
<item name="colorOnSurfaceInverse">@color/md_1_theme_light_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_1_theme_light_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_1_theme_light_inversePrimary</item>
</style>
</resources>

View File

@@ -1,3 +1,10 @@
# 0.1.4
# 1.0.0
- hotfix for those who crashed when opening an anime/manga
- **Bugfixes:**
- Fixed extension page hiding icons on first install
- Various bug/crash fixes
- Fixes for monochrome theme
- General theme tweaks
- **New Features:**
- added oled variant to all themes