Merge branch 'dev' into main

This commit is contained in:
rebelonion 2023-11-22 23:43:06 -06:00 committed by GitHub
commit 79d1c44e63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 988 additions and 243 deletions

View file

@ -21,16 +21,18 @@ android {
minSdk 23
targetSdk 34
versionCode ((System.currentTimeMillis() / 60000).toInteger())
versionName "1.0.0-beta03"
versionName "1.0.0-beta03i"
signingConfig signingConfigs.debug
}
buildTypes {
debug {
applicationIdSuffix ".beta"
manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher_beta"]
debuggable true
}
release {
manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher"]
debuggable false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
@ -76,11 +78,11 @@ dependencies {
// FireBase
implementation platform('com.google.firebase:firebase-bom:32.2.3')
implementation 'com.google.firebase:firebase-analytics-ktx:21.3.0'
implementation 'com.google.firebase:firebase-crashlytics-ktx:18.4.3'
implementation 'com.google.firebase:firebase-analytics-ktx:21.5.0'
implementation 'com.google.firebase:firebase-crashlytics-ktx:18.6.0'
// Exoplayer
ext.exo_version = '1.1.1'
ext.exo_version = '1.2.0'
implementation "androidx.media3:media3-exoplayer:$exo_version"
implementation "androidx.media3:media3-ui:$exo_version"
implementation "androidx.media3:media3-exoplayer-hls:$exo_version"

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>

View file

@ -22,6 +22,8 @@
<!-- For background jobs -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -46,7 +48,7 @@
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="${icon_placeholder}"
android:label="@string/app_name"
android:largeHeap="true"
android:requestLegacyExternalStorage="true"

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -83,9 +83,9 @@ class MainActivity : AppCompatActivity() {
private var uiSettings = UserInterfaceSettings()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
LangSet.setLocale(this)
ThemeManager(this).applyTheme()
LangSet.setLocale(this)
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

View file

@ -103,7 +103,7 @@ object Discord {
applicationId = "1163925779692912771"
smallImage = RPC.Link(
"Dantotsu",
"mp:attachments/1163940221063278672/1163940262423298141/bitmap1024.png"
"mp:attachments/1167176318266380288/1176997397797277856/logo-best_of_both.png"
)
buttons.add(RPC.Link("Stream on Dantotsu", "https://github.com/rebelonion/Dantotsu/"))
}

View file

@ -4,15 +4,18 @@ import android.annotation.SuppressLint
import android.app.Application.getProcessName
import android.os.Build
import android.os.Bundle
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import ani.dantotsu.R
import ani.dantotsu.connections.discord.Discord.saveToken
import ani.dantotsu.logger
import ani.dantotsu.startMainActivity
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.others.LangSet
import ani.dantotsu.snackString
class Login : AppCompatActivity() {
@ -34,28 +37,41 @@ ThemeManager(this).applyTheme()
settings.databaseEnabled = true
settings.domStorageEnabled = true
}
WebView.setWebContentsDebuggingEnabled(true)
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
if (url != null && url.endsWith("/app")) {
webView.stopLoading()
webView.evaluateJavascript("""
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
// Check if the URL is the one expected after a successful login
if (request?.url.toString() != "https://discord.com/login") {
// Delay the script execution to ensure the page is fully loaded
view?.postDelayed({
view.evaluateJavascript("""
(function() {
const wreq = webpackChunkdiscord_app.push([[Symbol()], {}, w => w])
webpackChunkdiscord_app.pop()
const token = Object.values(wreq.c).find(m => m.exports?.Z?.getToken).exports.Z.getToken();
return token;
const wreq = (webpackChunkdiscord_app.push([[''],{},e=>{m=[];for(let c in e.c)m.push(e.c[c])}]),m).find(m=>m?.exports?.default?.getToken!==void 0).exports.default.getToken();
return wreq;
})()
""".trimIndent()){
login(it.trim('"'))
}
}
""".trimIndent()) { result ->
login(result.trim('"'))
}
}, 2000)
}
return super.shouldOverrideUrlLoading(view, request)
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
}
}
webView.loadUrl("https://discord.com/login")
}
private fun login(token: String) {
if (token.isEmpty() || token == "null"){
snackString("Failed to retrieve token")
finish()
return
}
snackString("Logged in successfully")
finish()
saveToken(this, token)
startMainActivity(this@Login)

View file

@ -3,10 +3,12 @@ package ani.dantotsu.connections.discord
import ani.dantotsu.connections.discord.serializers.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@ -154,17 +156,15 @@ open class RPC(val token: String, val coroutineContext: CoroutineContext) {
webSocket.close(4000, "Interrupt")
}
//I hate this, but couldn't find any better way to solve it
suspend fun getUserData(): User {
var user : User? = null
//I kinda hate this
suspend fun getUserData(): User = suspendCancellableCoroutine { continuation ->
whenStarted = {
user = it
continuation.resume(it, onCancellation = null)
whenStarted = null
}
while (user == null) {
delay(100)
continuation.invokeOnCancellation {
whenStarted = null
}
return user!!
}
var onReceiveUserData: ((User) -> Deferred<Unit>)? = null
@ -185,7 +185,7 @@ open class RPC(val token: String, val coroutineContext: CoroutineContext) {
}
override fun onMessage(webSocket: WebSocket, text: String) {
println("Message : $text")
println("Discord Message : $text")
val map = json.decodeFromString<Res>(text)
seq = map.s

View file

@ -7,6 +7,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
@ -43,6 +44,7 @@ import ani.dantotsu.snackString
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.gson.GsonBuilder
import com.google.gson.InstanceCreator
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SChapterImpl
import kotlinx.coroutines.CoroutineScope
@ -79,8 +81,12 @@ class MangaDownloaderService : Service() {
setOnlyAlertOnce(true)
setProgress(0, 0, false)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(NOTIFICATION_ID, builder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
}else{
startForeground(NOTIFICATION_ID, builder.build())
ContextCompat.registerReceiver(this, cancelReceiver, IntentFilter(ACTION_CANCEL_DOWNLOAD), ContextCompat.RECEIVER_NOT_EXPORTED)
}
ContextCompat.registerReceiver(this, cancelReceiver, IntentFilter(ACTION_CANCEL_DOWNLOAD), ContextCompat.RECEIVER_EXPORTED)
}
override fun onDestroy() {

View file

@ -32,6 +32,7 @@ import ani.dantotsu.navBarHeight
import ani.dantotsu.px
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight
import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView
@ -84,12 +85,16 @@ class OfflineMangaFragment: Fragment() {
gridView.setOnItemClickListener { parent, view, position, id ->
// Get the OfflineMangaModel that was clicked
val item = adapter.getItem(position) as OfflineMangaModel
val media = downloadManager.mangaDownloads.filter { it.title == item.title }.first()
val media = downloadManager.mangaDownloads.filter { it.title == item.title }.firstOrNull()
media?.let {
startActivity(
Intent(requireContext(), MediaDetailsActivity::class.java)
.putExtra("media", getMedia(media))
.putExtra("media", getMedia(it))
.putExtra("download", true)
)
} ?: run {
snackString("no media found")
}
}
return view

View file

@ -270,27 +270,7 @@ class MediaDetailsViewModel : ViewModel() {
private val mangaChapter = MutableLiveData<MangaChapter?>(null)
fun getMangaChapter(): LiveData<MangaChapter?> = mangaChapter
suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, series: String, post: Boolean = true): Boolean {
//check if the chapter has been downloaded already
val downloadsManager = Injekt.get<DownloadsManager>()
if(downloadsManager.mangaDownloads.contains(Download(series, chapter.title!!, Download.Type.MANGA))) {
val download = downloadsManager.mangaDownloads.find { it.title == series && it.chapter == chapter.title!! } ?: return false
//look in the downloads folder for the chapter and add all the numerically named images to the chapter
val directory = File(
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Manga/$series/${chapter.title!!}"
)
val images = mutableListOf<MangaImage>()
directory.listFiles()?.forEach {
if (it.nameWithoutExtension.toIntOrNull() != null) {
images.add(MangaImage(FileUrl(it.absolutePath), false))
}
}
//sort the images by name
images.sortBy { it.url.url }
chapter.addImages(images)
if (post) mangaChapter.postValue(chapter)
return true
}
return tryWithSuspend(true) {
chapter.addImages(
mangaReadSources?.get(selected.sourceIndex)?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false

View file

@ -200,7 +200,7 @@ class AnimeWatchAdapter(
style = 2
fragment.onIconPressed(style, reversed)
}
binding.animeScanlatorTop.visibility= View.GONE
//Episode Handling
handleEpisodes()
}

View file

@ -321,6 +321,7 @@ class AnimeWatchFragment : Fragment() {
dialog.dismiss()
// Move the fragment transaction here
requireActivity().runOnUiThread {
val fragment =
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
@ -332,6 +333,7 @@ class AnimeWatchFragment : Fragment() {
.addToBackStack(null)
.commit()
}
}
.setNegativeButton("Cancel") { dialog, _ ->
dialog.cancel()
changeUIVisibility(true)
@ -340,7 +342,9 @@ class AnimeWatchFragment : Fragment() {
.show()
} else {
// If there's only one setting, proceed with the fragment transaction
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){
requireActivity().runOnUiThread {
val fragment =
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadEpisodes(media.selected!!.sourceIndex, true)
}
@ -350,6 +354,7 @@ class AnimeWatchFragment : Fragment() {
.addToBackStack(null)
.commit()
}
}
changeUIVisibility(false)
} else {

View file

@ -304,6 +304,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
1 -> ResourcesCompat.getFont(this, R.font.poppins_bold)
2 -> ResourcesCompat.getFont(this, R.font.poppins)
3 -> ResourcesCompat.getFont(this, R.font.poppins_thin)
4 -> ResourcesCompat.getFont(this, R.font.century_gothic_regular)
5 -> ResourcesCompat.getFont(this, R.font.century_gothic_bold)
else -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold)
}
playerView.subtitleView?.setStyle(
@ -1448,6 +1450,7 @@ ThemeManager(this).applyTheme()
override fun onResume() {
super.onResume()
LangSet.setLocale(this)
orientationListener?.enable()
hideSystemBars()
if (isInitialized) {

View file

@ -1,8 +1,12 @@
package ani.dantotsu.media.manga
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.lifecycle.coroutineScope
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R
import ani.dantotsu.databinding.ItemChapterListBinding
@ -10,8 +14,9 @@ import ani.dantotsu.databinding.ItemEpisodeCompactBinding
import ani.dantotsu.media.Media
import ani.dantotsu.setAnimation
import ani.dantotsu.connections.updateProgress
import java.util.regex.Matcher
import java.util.regex.Pattern
import ani.dantotsu.currContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MangaChapterAdapter(
private var type: Int,
@ -90,7 +95,7 @@ class MangaChapterAdapter(
}
}
fun removeDownload(chapterNumber: String) {
fun purgeDownload(chapterNumber: String) {
activeDownloads.remove(chapterNumber)
downloadedChapters.remove(chapterNumber)
// Find the position of the chapter and notify only that item
@ -112,6 +117,9 @@ class MangaChapterAdapter(
inner class ChapterListViewHolder(val binding: ItemChapterListBinding) :
RecyclerView.ViewHolder(binding.root) {
private val activeCoroutines = mutableSetOf<String>()
val typedValue1 = TypedValue()
val typedValue2 = TypedValue()
fun bind(chapterNumber: String, progress: String?) {
if (progress != null) {
binding.itemChapterTitle.visibility = View.VISIBLE
@ -122,18 +130,49 @@ class MangaChapterAdapter(
}
if (activeDownloads.contains(chapterNumber)) {
// Show spinner
binding.itemDownload.setImageResource(R.drawable.ic_round_refresh_24)
binding.itemDownload.setImageResource(R.drawable.ic_sync)
startOrContinueRotation(chapterNumber)
} else if (downloadedChapters.contains(chapterNumber)) {
// Show checkmark
binding.itemDownload.setImageResource(R.drawable.ic_check)
binding.itemDownload.setImageResource(R.drawable.ic_circle_check)
binding.itemDownload.setColorFilter(typedValue2.data)
binding.itemDownload.postDelayed({
binding.itemDownload.setImageResource(R.drawable.ic_circle_cancel)
binding.itemDownload.setColorFilter(typedValue2.data)
}, 1000)
} else {
// Show download icon
binding.itemDownload.setImageResource(R.drawable.ic_round_download_24)
binding.itemDownload.setImageResource(R.drawable.ic_circle_add)
}
}
private fun startOrContinueRotation(chapterNumber: String) {
if (!isRotationCoroutineRunningFor(chapterNumber)) {
val scope = fragment.lifecycle.coroutineScope
scope.launch {
// Add chapter number to active coroutines set
activeCoroutines.add(chapterNumber)
while (activeDownloads.contains(chapterNumber)) {
binding.itemDownload.animate().rotationBy(360f).setDuration(1000).setInterpolator(
LinearInterpolator()
).start()
delay(1000)
}
// Remove chapter number from active coroutines set
activeCoroutines.remove(chapterNumber)
}
}
}
private fun isRotationCoroutineRunningFor(chapterNumber: String): Boolean {
return chapterNumber in activeCoroutines
}
init {
val theme = currContext()?.theme
theme?.resolveAttribute(com.google.android.material.R.attr.colorError, typedValue1, true)
theme?.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue2, true)
itemView.setOnClickListener {
if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size)
fragment.onMangaChapterClick(arr[bindingAdapterPosition].number)

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.manga
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@ -16,7 +15,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.cardview.widget.CardView
import androidx.core.content.ContextCompat
import androidx.core.math.MathUtils.clamp
@ -42,7 +40,6 @@ import ani.dantotsu.parsers.HMangaSources
import ani.dantotsu.parsers.MangaParser
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
import ani.dantotsu.subcriptions.Notifications
import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP
@ -51,8 +48,6 @@ import ani.dantotsu.subcriptions.SubscriptionHelper
import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.navigationrail.NavigationRailView
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import eu.kanade.tachiyomi.source.ConfigurableSource
import kotlinx.coroutines.CoroutineScope
@ -110,7 +105,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
addAction(ACTION_DOWNLOAD_PROGRESS)
}
ContextCompat.registerReceiver(requireContext(), downloadStatusReceiver, intentFilter, ContextCompat.RECEIVER_NOT_EXPORTED)
ContextCompat.registerReceiver(requireContext(), downloadStatusReceiver, intentFilter, ContextCompat.RECEIVER_EXPORTED)
binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight)
screenWidth = resources.displayMetrics.widthPixels.dp
@ -405,7 +400,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
// Create a download task
val downloadTask = MangaDownloaderService.DownloadTask(
title = media.nameMAL ?: "",
title = media.nameMAL ?: media.nameRomaji,
chapter = chapter.title!!,
imageData = images,
sourceMedia = media,
@ -445,7 +440,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
fun onMangaChapterRemoveDownloadClick(i: String){
downloadManager.removeDownload(Download(media.nameMAL!!, i, Download.Type.MANGA))
downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA))
chapterAdapter.deleteDownload(i)
}
fun onMangaChapterStopDownloadClick(i: String) {
@ -456,8 +451,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
requireContext().sendBroadcast(cancelIntent)
// Remove the download from the manager and update the UI
downloadManager.removeDownload(Download(media.nameMAL!!, i, Download.Type.MANGA))
chapterAdapter.stopDownload(i)
downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA))
chapterAdapter.purgeDownload(i)
}
private val downloadStatusReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@ -475,7 +470,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
ACTION_DOWNLOAD_FAILED -> {
val chapterNumber = intent.getStringExtra(EXTRA_CHAPTER_NUMBER)
chapterNumber?.let {
chapterAdapter.removeDownload(it)
chapterAdapter.purgeDownload(it)
}
}

View file

@ -47,7 +47,7 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
loaded = true
binding.selectorAutoText.text = chp.title
lifecycleScope.launch(Dispatchers.IO) {
if(model.loadMangaChapterImages(chp, m.selected!!, m.nameMAL!!)) {
if(model.loadMangaChapterImages(chp, m.selected!!, m.nameMAL?:m.nameRomaji)) {
val activity = currActivity()
activity?.runOnUiThread {
tryWith { dismiss() }

View file

@ -317,7 +317,7 @@ ThemeManager(this).applyTheme()
}
}
scope.launch(Dispatchers.IO) { model.loadMangaChapterImages(chapter, media.selected!!, media.nameMAL!!) }
scope.launch(Dispatchers.IO) { model.loadMangaChapterImages(chapter, media.selected!!, media.nameMAL?:media.nameRomaji) }
}
private val snapHelper = PagerSnapHelper()
@ -706,7 +706,7 @@ ThemeManager(this).applyTheme()
model.loadMangaChapterImages(
chapters[chaptersArr.getOrNull(currentChapterIndex + 1) ?: return@launch]!!,
media.selected!!,
media.nameMAL!!,
media.nameMAL?:media.nameRomaji,
false
)
loading = false

View file

@ -174,7 +174,7 @@ object AppUpdater {
}
}
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
ContextCompat.RECEIVER_NOT_EXPORTED
ContextCompat.RECEIVER_EXPORTED
)
return true
}

View file

@ -0,0 +1,32 @@
package ani.dantotsu.others
class LanguageMapper {
companion object {
fun mapLanguageCodeToName(code: String): String {
return when (code) {
"all" -> "Multi"
"ar" -> "Arabic"
"de" -> "German"
"en" -> "English"
"es" -> "Spanish"
"fr" -> "French"
"id" -> "Indonesian"
"it" -> "Italian"
"ja" -> "Japanese"
"ko" -> "Korean"
"pl" -> "Polish"
"pt-BR" -> "Portuguese (Brazil)"
"ru" -> "Russian"
"th" -> "Thai"
"tr" -> "Turkish"
"uk" -> "Ukrainian"
"vi" -> "Vietnamese"
"zh" -> "Chinese"
"zh-Hans" -> "Chinese (Simplified)"
else -> ""
}
}
}
}

View file

@ -3,6 +3,7 @@ package ani.dantotsu.parsers
import android.os.Environment
import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.logger
import ani.dantotsu.media.manga.MangaNameAdapter
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
@ -47,6 +48,7 @@ class OfflineMangaParser: MangaParser() {
"Dantotsu/Manga/$chapterLink"
)
val images = mutableListOf<MangaImage>()
val imageNumberRegex = Regex("""(\d+)\.jpg$""")
if (directory.exists()) {
directory.listFiles()?.forEach {
if (it.isFile) {
@ -54,6 +56,13 @@ class OfflineMangaParser: MangaParser() {
images.add(image)
}
}
images.sortBy { image ->
val matchResult = imageNumberRegex.find(image.url.url)
matchResult?.groups?.get(1)?.value?.toIntOrNull() ?: Int.MAX_VALUE
}
for (image in images) {
logger("imageNumber: ${image.url.url}")
}
return images
}
return emptyList()

View file

@ -24,6 +24,7 @@ import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.others.LangSet
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -92,14 +93,14 @@ ThemeManager(this).applyTheme()
initActivity(this)
fun bind(extension: AnimeExtension.Available) {
binding.languageselect.setOnClickListener {
val popup = PopupMenu(this, it)
popup.inflate(R.menu.launguage_selector_menu)
popup.show()
}
}
binding.settingsContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = statusBarHeight
bottomMargin = navBarHeight

View file

@ -13,7 +13,6 @@ import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
@ -24,6 +23,8 @@ import androidx.viewpager2.widget.ViewPager2
import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.saveData
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
import com.google.android.material.tabs.TabLayout
import com.google.android.material.textfield.TextInputLayout
@ -62,12 +63,18 @@ class InstalledAnimeExtensionsFragment : Fragment() {
dialog.dismiss()
// Move the fragment transaction here
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){
val activity = requireActivity() as ExtensionsActivity
activity.findViewById<ViewPager2>(R.id.viewPager).visibility = View.VISIBLE
activity.findViewById<TabLayout>(R.id.tabLayout).visibility = View.VISIBLE
activity.findViewById<TextInputLayout>(R.id.searchView).visibility = View.VISIBLE
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
val eActivity = requireActivity() as ExtensionsActivity
eActivity.runOnUiThread {
val fragment =
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
eActivity.findViewById<ViewPager2>(R.id.viewPager).visibility =
View.VISIBLE
eActivity.findViewById<TabLayout>(R.id.tabLayout).visibility =
View.VISIBLE
eActivity.findViewById<TextInputLayout>(R.id.searchView).visibility =
View.VISIBLE
eActivity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
View.GONE
}
parentFragmentManager.beginTransaction()
@ -76,6 +83,7 @@ class InstalledAnimeExtensionsFragment : Fragment() {
.addToBackStack(null)
.commit()
}
}
.setNegativeButton("Cancel") { dialog, _ ->
dialog.cancel()
return@setNegativeButton
@ -83,12 +91,18 @@ class InstalledAnimeExtensionsFragment : Fragment() {
.show()
} else {
// If there's only one setting, proceed with the fragment transaction
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){
val activity = requireActivity() as ExtensionsActivity
activity.findViewById<ViewPager2>(R.id.viewPager).visibility = View.VISIBLE
activity.findViewById<TabLayout>(R.id.tabLayout).visibility = View.VISIBLE
activity.findViewById<TextInputLayout>(R.id.searchView).visibility = View.VISIBLE
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
val eActivity = requireActivity() as ExtensionsActivity
eActivity.runOnUiThread {
val fragment =
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
eActivity.findViewById<ViewPager2>(R.id.viewPager).visibility =
View.VISIBLE
eActivity.findViewById<TabLayout>(R.id.tabLayout).visibility =
View.VISIBLE
eActivity.findViewById<TextInputLayout>(R.id.searchView).visibility =
View.VISIBLE
eActivity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
View.GONE
}
parentFragmentManager.beginTransaction()
@ -97,6 +111,7 @@ class InstalledAnimeExtensionsFragment : Fragment() {
.addToBackStack(null)
.commit()
}
}
// Hide ViewPager2 and TabLayout
val activity = requireActivity() as ExtensionsActivity
@ -148,7 +163,7 @@ class InstalledAnimeExtensionsFragment : Fragment() {
context,
Notifications.CHANNEL_DOWNLOADER_PROGRESS
)
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
.setSmallIcon(R.drawable.ic_circle_check)
.setContentTitle("Update complete")
.setContentText("The extension has been successfully updated.")
.setPriority(NotificationCompat.PRIORITY_LOW)
@ -191,13 +206,11 @@ class InstalledAnimeExtensionsFragment : Fragment() {
private class AnimeExtensionsAdapter(
private val onSettingsClicked: (AnimeExtension.Installed) -> Unit,
private val onUninstallClicked: (AnimeExtension.Installed) -> Unit,
skipIcons: Boolean
val 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
}
@ -210,14 +223,10 @@ class InstalledAnimeExtensionsFragment : Fragment() {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter
val nsfw = if (extension.isNsfw) {
"(18+)"
} else {
""
}
val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang= LanguageMapper.mapLanguageCodeToName(extension.lang)
holder.extensionNameTextView.text = extension.name
holder.extensionVersionTextView.text = "${extension.versionName} $nsfw"
holder.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw"
if (!skipIcons) {
holder.extensionIconImageView.setImageDrawable(extension.icon)
}

View file

@ -14,7 +14,6 @@ import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
@ -26,6 +25,7 @@ import ani.dantotsu.R
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
import ani.dantotsu.loadData
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
import ani.dantotsu.others.LanguageMapper
import com.google.android.material.tabs.TabLayout
import com.google.android.material.textfield.TextInputLayout
import com.google.firebase.crashlytics.FirebaseCrashlytics
@ -204,13 +204,10 @@ class InstalledMangaExtensionsFragment : Fragment() {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter
val nsfw = if (extension.isNsfw) {
"(18+)"
} else {
""
}
val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang = LanguageMapper.mapLanguageCodeToName(extension.lang)
holder.extensionNameTextView.text = extension.name
holder.extensionVersionTextView.text = "${extension.versionName} $nsfw"
holder.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw"
if (!skipIcons) {
holder.extensionIconImageView.setImageDrawable(extension.icon)
}

View file

@ -378,7 +378,7 @@ ThemeManager(this).applyTheme()
dialog.dismiss()
}.show()
}
val fonts = arrayOf("Poppins Semi Bold", "Poppins Bold", "Poppins", "Poppins Thin")
val fonts = arrayOf("Poppins Semi Bold", "Poppins Bold", "Poppins", "Poppins Thin","Century Gothic","Century Gothic Bold")
val fontDialog = AlertDialog.Builder(this, R.style.DialogTheme).setTitle(getString(R.string.subtitle_font))
binding.videoSubFont.setOnClickListener {
fontDialog.setSingleChoiceItems(fonts, settings.font) { dialog, count ->

View file

@ -35,6 +35,7 @@ import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.others.LangSet
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.network.NetworkPreferences
import io.noties.markwon.Markwon
@ -176,11 +177,27 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
}
binding.userAgent.setText(networkPreferences.defaultUserAgent().get())
binding.userAgent.setOnEditorActionListener { _, _, _ ->
networkPreferences.defaultUserAgent().set(binding.userAgent.text.toString())
true
// binding.userAgent.setText(networkPreferences.defaultUserAgent().get())
binding.userAgent.setOnClickListener{
val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
val editText = dialogView.findViewById<TextInputEditText>(R.id.userAgentTextBox)
editText.setText(networkPreferences.defaultUserAgent().get())
val alertDialog = AlertDialog.Builder(this)
.setView(dialogView)
.setPositiveButton("OK") { dialog, _ ->
networkPreferences.defaultUserAgent().set(editText.text.toString())
dialog.dismiss()
}
.setNegativeButton("Reset") { dialog, _ ->
networkPreferences.defaultUserAgent().set("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0") // Reset to default or empty
editText.setText("")
dialog.dismiss()
}
.create()
alertDialog.show()
}
val exDns = listOf("None", "Cloudflare", "Google", "AdGuard", "Quad9", "AliDNS", "DNSPod", "360", "Quad101", "Mullvad", "Controld", "Njalla", "Shecan", "Libre")
binding.settingsExtensionDns.setText(exDns[networkPreferences.dohProvider().get()], false)

View file

@ -44,7 +44,7 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
onCloseAction?.invoke()
}
fun populateAnimePreferenceScreen(): PreferenceScreen {
private fun populateAnimePreferenceScreen(): PreferenceScreen {
val sourceId = requireArguments().getLong(SOURCE_ID)
val source = Injekt.get<AnimeSourceManager>().get(sourceId)!!
check(source is ConfigurableAnimeSource)
@ -57,11 +57,11 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
pref.isIconSpaceReserved = false
if (pref is DialogPreference) {
pref.dialogTitle = pref.title
println("pref.dialogTitle: ${pref.dialogTitle}")
//println("pref.dialogTitle: ${pref.dialogTitle}")
}
for (entry in sharedPreferences.all.entries) {
/*for (entry in sharedPreferences.all.entries) {
Log.d("Preferences", "Key: ${entry.key}, Value: ${entry.value}")
}
}*/
// Apply incognito IME for EditTextPreference
if (pref is EditTextPreference) {

View file

@ -1,5 +1,6 @@
package ani.dantotsu.settings.paging
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
@ -15,9 +16,9 @@ import androidx.paging.PagingState
import androidx.paging.cachedIn
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.settings.SettingsActivity
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
@ -78,7 +79,8 @@ class AnimeExtensionPagingSource(
val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet()
val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions }
val query = searchQuery.first()
var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: true
val isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false
val filteredExtensions = if (query.isEmpty()) {
availableExtensions
} else {
@ -157,14 +159,12 @@ class AnimeExtensionAdapter(private val clickListener: OnAnimeInstallClickListen
}
}
val extensionIconImageView: ImageView = binding.extensionIconImageView
fun bind(extension: AnimeExtension.Available) {
val nsfw = if (extension.isNsfw) {
"(18+)"
} else {
""
}
val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang= LanguageMapper.mapLanguageCodeToName(extension.lang)
binding.extensionNameTextView.text = extension.name
binding.extensionVersionTextView.text = "${extension.versionName} $nsfw"
binding.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw"
}
}
}

View file

@ -1,6 +1,6 @@
package ani.dantotsu.settings.paging
import android.util.Log
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
@ -16,9 +16,9 @@ import androidx.paging.PagingState
import androidx.paging.cachedIn
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.settings.SettingsActivity
import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
@ -28,7 +28,6 @@ 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
@ -82,7 +81,7 @@ class MangaExtensionPagingSource(
val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet()
val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions }
val query = searchQuery.first()
var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false
val isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false
val filteredExtensions = if (query.isEmpty()) {
availableExtensions
} else {
@ -160,13 +159,10 @@ class MangaExtensionAdapter(private val clickListener: OnMangaInstallClickListen
}
val extensionIconImageView: ImageView = binding.extensionIconImageView
fun bind(extension: MangaExtension.Available) {
val nsfw = if (extension.isNsfw) {
"(18+)"
} else {
""
}
val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang= LanguageMapper.mapLanguageCodeToName(extension.lang)
binding.extensionNameTextView.text = extension.name
binding.extensionVersionTextView.text = "${extension.versionName} $nsfw"
binding.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw"
}
}
}

View file

@ -9,6 +9,7 @@ import android.content.IntentFilter
import android.content.pm.PackageInstaller
import android.os.Build
import androidx.core.content.ContextCompat
import ani.dantotsu.snackString
import eu.kanade.tachiyomi.extension.InstallStep
import eu.kanade.tachiyomi.util.lang.use
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
@ -72,12 +73,18 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn
service,
activeSession!!.second,
Intent(INSTALL_ACTION),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_MUTABLE
} else 0
).intentSender
session.commit(intentSender)
}
} catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
logcat(LogPriority.ERROR) { "Exception: $e" }
snackString("Failed to install extension ${entry.downloadId} ${entry.uri}")
activeSession?.let { (_, sessionId) ->
packageInstaller.abandonSession(sessionId)
}
@ -101,7 +108,7 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn
}
init {
ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED)
ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_EXPORTED)
}
}

View file

@ -28,7 +28,7 @@ internal class AnimeExtensionInstallReceiver(private val listener: Listener) :
* Registers this broadcast receiver
*/
fun register(context: Context) {
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_NOT_EXPORTED)
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED)
}
/**

View file

@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.extension.anime.util
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.net.Uri
import android.os.Build
import android.os.IBinder
import eu.kanade.domain.base.BasePreferences
import ani.dantotsu.R
@ -29,8 +31,12 @@ class AnimeExtensionInstallService : Service() {
setContentTitle("Installing Anime Extension...")
setProgress(100, 100, true)
}.build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(Notifications.ID_EXTENSION_INSTALLER, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
}else{
startForeground(Notifications.ID_EXTENSION_INSTALLER, notification)
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val uri = intent?.data

View file

@ -9,6 +9,7 @@ import android.content.IntentFilter
import android.content.pm.PackageInstaller
import android.os.Build
import androidx.core.content.ContextCompat
import ani.dantotsu.snackString
import eu.kanade.tachiyomi.extension.InstallStep
import eu.kanade.tachiyomi.util.lang.use
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
@ -72,12 +73,18 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa
service,
activeSession!!.second,
Intent(INSTALL_ACTION),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_MUTABLE
} else 0
).intentSender
session.commit(intentSender)
}
} catch (e: Exception) {
logcat(LogPriority.ERROR) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
logcat(LogPriority.ERROR) { "Exception: $e" }
snackString("Failed to install extension ${entry.downloadId} ${entry.uri}")
activeSession?.let { (_, sessionId) ->
packageInstaller.abandonSession(sessionId)
}
@ -101,7 +108,7 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa
}
init {
ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED)
ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_EXPORTED)
}
}

View file

@ -28,7 +28,7 @@ internal class MangaExtensionInstallReceiver(private val listener: Listener) :
* Registers this broadcast receiver
*/
fun register(context: Context) {
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_NOT_EXPORTED)
ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED)
}
/**

View file

@ -3,7 +3,11 @@ package eu.kanade.tachiyomi.extension.manga.util
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
import android.net.Uri
import android.os.Build
import android.os.IBinder
import ani.dantotsu.R
import eu.kanade.domain.base.BasePreferences
@ -29,8 +33,12 @@ class MangaExtensionInstallService : Service() {
setContentTitle("Installing manga extension...")
setProgress(100, 100, true)
}.build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(Notifications.ID_EXTENSION_INSTALLER, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
}else{
startForeground(Notifications.ID_EXTENSION_INSTALLER, notification)
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val uri = intent?.data

View file

@ -0,0 +1,377 @@
<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:name="vector"
android:width="768dp"
android:height="768dp"
android:viewportWidth="768"
android:viewportHeight="768">
<group
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="#6901fd"
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="#4800e5"
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="#2000bd"
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="#1e00d1"
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="#2900da"
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="wrapper">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="scaleX"
android:duration="500"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="500"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
</set>
</aapt:attr>
</target>
<target android:name="group_6">
<aapt:attr name="android:animation">
<set>
<objectAnimator
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:valueFrom="1.2"
android:valueTo="1"
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="group_3">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="translateX"
android:startOffset="250"
android:duration="400"
android:valueFrom="-360"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="@android:anim/overshoot_interpolator"/>
</aapt:attr>
</target>
<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: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: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,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M440,680h80v-160h160v-80L520,440v-160h-80v160L280,440v80h160v160ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="m336,680 l144,-144 144,144 56,-56 -144,-144 144,-144 -56,-56 -144,144 -144,-144 -56,56 144,144 -144,144 56,56ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="m424,664 l282,-282 -56,-56 -226,226 -114,-114 -56,56 170,170ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"/>
</vector>

View file

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="768"
android:viewportHeight="768">
<group>
<clip-path
android:pathData="M125.71,125.71h516.58v516.58h-516.58z"/>
<path
android:pathData="M123.53,128.02h512v511.96h-512z"
android:strokeWidth="0"
android:fillColor="#6901fd"/>
<path
android:pathData="m117.58,129.49v335.26c23.32,3.7 47.23,5.63 71.58,5.63 211.59,0 389.34,-144.9 439.43,-340.89H117.58Z"
android:strokeWidth="0"
android:fillColor="#2000bd"/>
<path
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="#4800e5"/>
<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="#1e00d1"/>
<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="#2900da"/>
</group>
</vector>

View file

@ -0,0 +1,22 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="768"
android:viewportHeight="768">
<group>
<clip-path
android:pathData="M125.71,125.71h516.58v516.58h-516.58z"/>
<path
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="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="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,20 +1,4 @@
<vector android:height="24dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#00000000" android:pathData="M10,12V17"
android:strokeColor="#000000" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="#00000000" android:pathData="M14,12V17"
android:strokeColor="#000000" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="#00000000" android:pathData="M4,7H20"
android:strokeColor="#000000" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="#00000000"
android:pathData="M6,10V18C6,19.657 7.343,21 9,21H15C16.657,21 18,19.657 18,18V10"
android:strokeColor="#000000" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="#00000000"
android:pathData="M9,5C9,3.895 9.895,3 11,3H13C14.105,3 15,3.895 15,5V7H9V5Z"
android:strokeColor="#000000" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="#000000" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M160,800v-80h110l-16,-14q-52,-46 -73,-105t-21,-119q0,-111 66.5,-197.5T400,170v84q-72,26 -116,88.5T240,482q0,45 17,87.5t53,78.5l10,10v-98h80v240L160,800ZM560,790v-84q72,-26 116,-88.5T720,478q0,-45 -17,-87.5T650,312l-10,-10v98h-80v-240h240v80L690,240l16,14q49,49 71.5,106.5T800,478q0,111 -66.5,197.5T560,790Z"/>
</vector>

Binary file not shown.

Binary file not shown.

View file

@ -550,24 +550,46 @@
app:showText="false"
app:thumbTint="@color/button_switch_track" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<com.google.android.material.textfield.TextInputEditText
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="-16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="-16dp"
android:background="?android:attr/listDivider" />
<Button
android:id="@+id/userAgent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="user agent"
app:boxCornerRadiusBottomEnd="8dp"
app:boxCornerRadiusBottomStart="8dp"
app:boxCornerRadiusTopEnd="8dp"
app:boxCornerRadiusTopStart="8dp"
app:hintAnimationEnabled="true" />
android:layout_height="64dp"
android:layout_marginStart="-32dp"
android:layout_marginEnd="-32dp"
android:background="@drawable/ui_bg"
android:backgroundTint="?attr/colorSecondary"
android:backgroundTintMode="src_atop"
android:fontFamily="@font/poppins_bold"
android:insetTop="0dp"
android:insetBottom="0dp"
android:paddingStart="32dp"
android:paddingEnd="32dp"
android:text="@string/user_agent"
android:textAlignment="viewStart"
android:textAllCaps="false"
android:textColor="?attr/colorOnBackground"
app:cornerRadius="0dp"
app:icon="@drawable/ic_round_video_settings_24"
app:iconPadding="16dp"
app:iconSize="24dp"
app:iconTint="?attr/colorPrimary" />
</com.google.android.material.textfield.TextInputLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="-16dp"
android:layout_marginEnd="-16dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/listDivider" />
<TextView
android:layout_width="match_parent"

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="16dp">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/userAgentTextBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/user_agent"
app:boxCornerRadiusBottomEnd="8dp"
app:boxCornerRadiusBottomStart="8dp"
app:boxCornerRadiusTopEnd="8dp"
app:boxCornerRadiusTopStart="8dp"
app:hintAnimationEnabled="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>

View file

@ -97,6 +97,8 @@
android:layout_height="0dp"
android:layout_weight="1"
android:numColumns="auto_fit"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:columnWidth="108dp"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"

View file

@ -9,7 +9,7 @@
app:cardCornerRadius="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="312dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
@ -49,17 +49,18 @@
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@font/poppins_bold"
android:maxWidth="250dp"
android:paddingEnd="8dp"
android:singleLine="true"
android:textSize="14dp"
tools:ignore="SpUsage"
android:paddingEnd="8dp"
tools:text="1" />
</LinearLayout>
<TextView
android:id="@+id/itemChapterTitle"
android:layout_width="match_parent"
android:layout_width="312dp"
android:layout_height="wrap_content"
android:alpha="0.66"
android:ellipsize="end"
@ -92,9 +93,8 @@
android:id="@+id/itemEpisodeViewed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_margin="8dp"
android:visibility="gone"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="40dp"
app:srcCompat="@drawable/ic_round_remove_red_eye_24"
tools:ignore="ContentDescription" />

View file

@ -33,8 +33,9 @@
android:id="@+id/extensionVersionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_semi_bold"
android:text="version"
android:textSize="11sp" />
android:textSize="10sp" />
</LinearLayout>
<ImageView
@ -44,7 +45,6 @@
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:layout_weight="0"
android:contentDescription="Settings"
android:src="@drawable/ic_round_dots_vertical_24"
app:tint="?attr/colorOnBackground" />
@ -54,7 +54,6 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="0"
android:contentDescription="uninstall"
android:src="@drawable/ic_round_delete_24"
app:tint="?attr/colorOnBackground" />

View file

@ -2,6 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp">
@ -32,8 +33,9 @@
android:id="@+id/extensionVersionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1"
android:textSize="11sp" />
android:fontFamily="@font/poppins_semi_bold"
android:text="version"
android:textSize="10sp" />
</LinearLayout>
<ImageView
@ -41,8 +43,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textStyle="bold"
android:src="@drawable/ic_round_download_24"
android:textColor="?attr/colorPrimary"
android:textSize="14sp"/>
android:textSize="14sp"
app:tint="?attr/colorOnBackground"/>
</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="@color/bg_black">
android:background="?android:colorBackground">
<ImageView
android:id="@+id/splashImage"

View file

@ -2,14 +2,102 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/all"
android:title="All" />
android:title="All"
android:checkable="true"
android:checked="true" />
<item
android:id="@+id/multi"
android:title="Multi" />
android:title="Multi"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/arabic"
android:title="Arabic"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/german"
android:title="German"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/english"
android:title="English" />
android:title="English"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/abcd"
android:title="abcd" />
android:id="@+id/spanish"
android:title="Spanish"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/french"
android:title="French"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/indonesian"
android:title="Indonesian"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/italian"
android:title="Italian"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/japanese"
android:title="Japanese"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/korean"
android:title="Korean"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/polish"
android:title="Polish"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/portuguese_brazil"
android:title="Portuguese (Brazil)"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/russian"
android:title="Russian"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/thai"
android:title="Thai"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/turkish"
android:title="Turkish"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/ukrainian"
android:title="Ukrainian"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/vietnamese"
android:title="Vietnamese"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/chinese"
android:title="Chinese"
android:checkable="true"
android:checked="false" />
<item
android:id="@+id/chinese_simplified"
android:title="Chinese (Simplified)"
android:checkable="true"
android:checked="false" />
</menu>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_beta_background"/>
<foreground android:drawable="@drawable/ic_launcher_beta_foreground"/>
<monochrome android:drawable="@drawable/mono"/>
</adaptive-icon>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_beta_background"/>
<foreground android:drawable="@drawable/ic_launcher_beta_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -1,4 +1,4 @@
<resources>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Dantotsu" parent="Theme.Base">
<item name="android:statusBarColor">@color/status</item>
<item name="colorOnPrimary">@color/bg_black</item>

View file

@ -155,7 +155,7 @@
<string name="sequel">Sequel</string>
<string name="anilist_settings">Anilist Settings</string>
<string name="extension_settings">Extension</string>
<string name="extension_settings">Extensions</string>
<string name="downloads">Downloads</string>
<string name="settings">Settings</string>
<string name="extensions">Extensions</string>
@ -631,5 +631,6 @@
<string name="use_material_you">Use Material You</string>
<string name="extension_specific_dns">Extension-specific DNS</string>
<string name="theme_">Theme:</string>
<string name="user_agent">User Agent</string>
</resources>

View file

@ -18,7 +18,6 @@
<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>
<item name="android:windowSplashScreenBackground" tools:targetApi="s">@color/bg_black</item>
</style>
<style name="Theme.Dantotsu" parent="Theme.Base">