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

View file

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

View file

@ -22,6 +22,8 @@
<!-- For background jobs --> <!-- For background jobs -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <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.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -46,7 +48,7 @@
<application <application
android:name=".App" android:name=".App"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="${icon_placeholder}"
android:label="@string/app_name" android:label="@string/app_name"
android:largeHeap="true" android:largeHeap="true"
android:requestLegacyExternalStorage="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() private var uiSettings = UserInterfaceSettings()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
LangSet.setLocale(this)
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
LangSet.setLocale(this)
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)

View file

@ -103,7 +103,7 @@ object Discord {
applicationId = "1163925779692912771" applicationId = "1163925779692912771"
smallImage = RPC.Link( smallImage = RPC.Link(
"Dantotsu", "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/")) 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.app.Application.getProcessName
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.webkit.WebResourceRequest
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.connections.discord.Discord.saveToken import ani.dantotsu.connections.discord.Discord.saveToken
import ani.dantotsu.logger
import ani.dantotsu.startMainActivity import ani.dantotsu.startMainActivity
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.others.LangSet import ani.dantotsu.others.LangSet
import ani.dantotsu.snackString
class Login : AppCompatActivity() { class Login : AppCompatActivity() {
@ -20,7 +23,7 @@ class Login : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
LangSet.setLocale(this) LangSet.setLocale(this)
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val process = getProcessName() val process = getProcessName()
if (packageName != process) WebView.setDataDirectorySuffix(process) if (packageName != process) WebView.setDataDirectorySuffix(process)
@ -34,28 +37,41 @@ ThemeManager(this).applyTheme()
settings.databaseEnabled = true settings.databaseEnabled = true
settings.domStorageEnabled = true settings.domStorageEnabled = true
} }
WebView.setWebContentsDebuggingEnabled(true)
webView.webViewClient = object : WebViewClient() { webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) { override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
if (url != null && url.endsWith("/app")) { // Check if the URL is the one expected after a successful login
webView.stopLoading() if (request?.url.toString() != "https://discord.com/login") {
webView.evaluateJavascript(""" // Delay the script execution to ensure the page is fully loaded
(function() { view?.postDelayed({
const wreq = webpackChunkdiscord_app.push([[Symbol()], {}, w => w]) view.evaluateJavascript("""
webpackChunkdiscord_app.pop() (function() {
const token = Object.values(wreq.c).find(m => m.exports?.Z?.getToken).exports.Z.getToken(); 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 token; return wreq;
})() })()
""".trimIndent()){ """.trimIndent()) { result ->
login(it.trim('"')) 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") webView.loadUrl("https://discord.com/login")
} }
private fun login(token: String) { private fun login(token: String) {
if (token.isEmpty() || token == "null"){
snackString("Failed to retrieve token")
finish()
return
}
snackString("Logged in successfully")
finish() finish()
saveToken(this, token) saveToken(this, token)
startMainActivity(this@Login) startMainActivity(this@Login)

View file

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

View file

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

View file

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

View file

@ -270,27 +270,7 @@ class MediaDetailsViewModel : ViewModel() {
private val mangaChapter = MutableLiveData<MangaChapter?>(null) private val mangaChapter = MutableLiveData<MangaChapter?>(null)
fun getMangaChapter(): LiveData<MangaChapter?> = mangaChapter fun getMangaChapter(): LiveData<MangaChapter?> = mangaChapter
suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, series: String, post: Boolean = true): Boolean { suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, series: String, post: Boolean = true): Boolean {
//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) { return tryWithSuspend(true) {
chapter.addImages( chapter.addImages(
mangaReadSources?.get(selected.sourceIndex)?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false mangaReadSources?.get(selected.sourceIndex)?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false

View file

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

View file

@ -321,16 +321,18 @@ class AnimeWatchFragment : Fragment() {
dialog.dismiss() dialog.dismiss()
// Move the fragment transaction here // Move the fragment transaction here
val fragment = requireActivity().runOnUiThread {
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){ val fragment =
changeUIVisibility(true) AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
loadEpisodes(media.selected!!.sourceIndex, true) changeUIVisibility(true)
} loadEpisodes(media.selected!!.sourceIndex, true)
parentFragmentManager.beginTransaction() }
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down) parentFragmentManager.beginTransaction()
.replace(R.id.fragmentExtensionsContainer, fragment) .setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
.addToBackStack(null) .replace(R.id.fragmentExtensionsContainer, fragment)
.commit() .addToBackStack(null)
.commit()
}
} }
.setNegativeButton("Cancel") { dialog, _ -> .setNegativeButton("Cancel") { dialog, _ ->
dialog.cancel() dialog.cancel()
@ -340,15 +342,18 @@ class AnimeWatchFragment : Fragment() {
.show() .show()
} else { } else {
// If there's only one setting, proceed with the fragment transaction // If there's only one setting, proceed with the fragment transaction
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){ requireActivity().runOnUiThread {
changeUIVisibility(true) val fragment =
loadEpisodes(media.selected!!.sourceIndex, true) AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) {
changeUIVisibility(true)
loadEpisodes(media.selected!!.sourceIndex, true)
}
parentFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
.replace(R.id.fragmentExtensionsContainer, fragment)
.addToBackStack(null)
.commit()
} }
parentFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
.replace(R.id.fragmentExtensionsContainer, fragment)
.addToBackStack(null)
.commit()
} }
changeUIVisibility(false) changeUIVisibility(false)

View file

@ -304,6 +304,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
1 -> ResourcesCompat.getFont(this, R.font.poppins_bold) 1 -> ResourcesCompat.getFont(this, R.font.poppins_bold)
2 -> ResourcesCompat.getFont(this, R.font.poppins) 2 -> ResourcesCompat.getFont(this, R.font.poppins)
3 -> ResourcesCompat.getFont(this, R.font.poppins_thin) 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) else -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold)
} }
playerView.subtitleView?.setStyle( playerView.subtitleView?.setStyle(
@ -321,7 +323,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
LangSet.setLocale(this) LangSet.setLocale(this)
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
binding = ActivityExoplayerBinding.inflate(layoutInflater) binding = ActivityExoplayerBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
@ -1448,6 +1450,7 @@ ThemeManager(this).applyTheme()
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
LangSet.setLocale(this)
orientationListener?.enable() orientationListener?.enable()
hideSystemBars() hideSystemBars()
if (isInitialized) { if (isInitialized) {

View file

@ -1,8 +1,12 @@
package ani.dantotsu.media.manga package ani.dantotsu.media.manga
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.lifecycle.coroutineScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.databinding.ItemChapterListBinding import ani.dantotsu.databinding.ItemChapterListBinding
@ -10,8 +14,9 @@ import ani.dantotsu.databinding.ItemEpisodeCompactBinding
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.setAnimation import ani.dantotsu.setAnimation
import ani.dantotsu.connections.updateProgress import ani.dantotsu.connections.updateProgress
import java.util.regex.Matcher import ani.dantotsu.currContext
import java.util.regex.Pattern import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MangaChapterAdapter( class MangaChapterAdapter(
private var type: Int, private var type: Int,
@ -90,7 +95,7 @@ class MangaChapterAdapter(
} }
} }
fun removeDownload(chapterNumber: String) { fun purgeDownload(chapterNumber: String) {
activeDownloads.remove(chapterNumber) activeDownloads.remove(chapterNumber)
downloadedChapters.remove(chapterNumber) downloadedChapters.remove(chapterNumber)
// Find the position of the chapter and notify only that item // Find the position of the chapter and notify only that item
@ -112,6 +117,9 @@ class MangaChapterAdapter(
inner class ChapterListViewHolder(val binding: ItemChapterListBinding) : inner class ChapterListViewHolder(val binding: ItemChapterListBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
private val activeCoroutines = mutableSetOf<String>()
val typedValue1 = TypedValue()
val typedValue2 = TypedValue()
fun bind(chapterNumber: String, progress: String?) { fun bind(chapterNumber: String, progress: String?) {
if (progress != null) { if (progress != null) {
binding.itemChapterTitle.visibility = View.VISIBLE binding.itemChapterTitle.visibility = View.VISIBLE
@ -122,18 +130,49 @@ class MangaChapterAdapter(
} }
if (activeDownloads.contains(chapterNumber)) { if (activeDownloads.contains(chapterNumber)) {
// Show spinner // 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)) { } else if (downloadedChapters.contains(chapterNumber)) {
// Show checkmark // 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 { } else {
// Show download icon // 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 { 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 { itemView.setOnClickListener {
if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size) if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size)
fragment.onMangaChapterClick(arr[bindingAdapterPosition].number) fragment.onMangaChapterClick(arr[bindingAdapterPosition].number)

View file

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

View file

@ -47,7 +47,7 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
loaded = true loaded = true
binding.selectorAutoText.text = chp.title binding.selectorAutoText.text = chp.title
lifecycleScope.launch(Dispatchers.IO) { 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() val activity = currActivity()
activity?.runOnUiThread { activity?.runOnUiThread {
tryWith { dismiss() } 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() private val snapHelper = PagerSnapHelper()
@ -706,7 +706,7 @@ ThemeManager(this).applyTheme()
model.loadMangaChapterImages( model.loadMangaChapterImages(
chapters[chaptersArr.getOrNull(currentChapterIndex + 1) ?: return@launch]!!, chapters[chaptersArr.getOrNull(currentChapterIndex + 1) ?: return@launch]!!,
media.selected!!, media.selected!!,
media.nameMAL!!, media.nameMAL?:media.nameRomaji,
false false
) )
loading = false loading = false

View file

@ -174,7 +174,7 @@ object AppUpdater {
} }
} }
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), }, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
ContextCompat.RECEIVER_NOT_EXPORTED ContextCompat.RECEIVER_EXPORTED
) )
return true 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 android.os.Environment
import ani.dantotsu.currContext import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.logger
import ani.dantotsu.media.manga.MangaNameAdapter import ani.dantotsu.media.manga.MangaNameAdapter
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
@ -47,6 +48,7 @@ class OfflineMangaParser: MangaParser() {
"Dantotsu/Manga/$chapterLink" "Dantotsu/Manga/$chapterLink"
) )
val images = mutableListOf<MangaImage>() val images = mutableListOf<MangaImage>()
val imageNumberRegex = Regex("""(\d+)\.jpg$""")
if (directory.exists()) { if (directory.exists()) {
directory.listFiles()?.forEach { directory.listFiles()?.forEach {
if (it.isFile) { if (it.isFile) {
@ -54,6 +56,13 @@ class OfflineMangaParser: MangaParser() {
images.add(image) 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 images
} }
return emptyList() return emptyList()

View file

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

View file

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

View file

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

View file

@ -378,7 +378,7 @@ ThemeManager(this).applyTheme()
dialog.dismiss() dialog.dismiss()
}.show() }.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)) val fontDialog = AlertDialog.Builder(this, R.style.DialogTheme).setTitle(getString(R.string.subtitle_font))
binding.videoSubFont.setOnClickListener { binding.videoSubFont.setOnClickListener {
fontDialog.setSingleChoiceItems(fonts, settings.font) { dialog, count -> 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.themes.ThemeManager
import ani.dantotsu.others.LangSet import ani.dantotsu.others.LangSet
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.NetworkPreferences
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
@ -176,12 +177,28 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
} }
binding.userAgent.setText(networkPreferences.defaultUserAgent().get()) // binding.userAgent.setText(networkPreferences.defaultUserAgent().get())
binding.userAgent.setOnEditorActionListener { _, _, _ -> binding.userAgent.setOnClickListener{
networkPreferences.defaultUserAgent().set(binding.userAgent.text.toString()) val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null)
true 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") 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) binding.settingsExtensionDns.setText(exDns[networkPreferences.dohProvider().get()], false)
binding.settingsExtensionDns.setAdapter(ArrayAdapter(this, R.layout.item_dropdown, exDns)) binding.settingsExtensionDns.setAdapter(ArrayAdapter(this, R.layout.item_dropdown, exDns))

View file

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

View file

@ -1,5 +1,6 @@
package ani.dantotsu.settings.paging package ani.dantotsu.settings.paging
import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
@ -15,9 +16,9 @@ import androidx.paging.PagingState
import androidx.paging.cachedIn import androidx.paging.cachedIn
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.settings.SettingsActivity
import ani.dantotsu.databinding.ItemExtensionAllBinding import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
@ -78,7 +79,8 @@ class AnimeExtensionPagingSource(
val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet() val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet()
val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions } val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions }
val query = searchQuery.first() val query = searchQuery.first()
var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: true val isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false
val filteredExtensions = if (query.isEmpty()) { val filteredExtensions = if (query.isEmpty()) {
availableExtensions availableExtensions
} else { } else {
@ -157,14 +159,12 @@ class AnimeExtensionAdapter(private val clickListener: OnAnimeInstallClickListen
} }
} }
val extensionIconImageView: ImageView = binding.extensionIconImageView val extensionIconImageView: ImageView = binding.extensionIconImageView
fun bind(extension: AnimeExtension.Available) { fun bind(extension: AnimeExtension.Available) {
val nsfw = if (extension.isNsfw) { val nsfw = if (extension.isNsfw) "(18+)" else ""
"(18+)" val lang= LanguageMapper.mapLanguageCodeToName(extension.lang)
} else {
""
}
binding.extensionNameTextView.text = extension.name 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 package ani.dantotsu.settings.paging
import android.util.Log import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
@ -16,9 +16,9 @@ import androidx.paging.PagingState
import androidx.paging.cachedIn import androidx.paging.cachedIn
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import ani.dantotsu.settings.SettingsActivity
import ani.dantotsu.databinding.ItemExtensionAllBinding import ani.dantotsu.databinding.ItemExtensionAllBinding
import ani.dantotsu.loadData import ani.dantotsu.loadData
import ani.dantotsu.others.LanguageMapper
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension 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.StateFlow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import java.lang.Math.min
class MangaExtensionsViewModelFactory( class MangaExtensionsViewModelFactory(
private val mangaExtensionManager: MangaExtensionManager private val mangaExtensionManager: MangaExtensionManager
@ -82,7 +81,7 @@ class MangaExtensionPagingSource(
val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet() val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet()
val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions } val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions }
val query = searchQuery.first() val query = searchQuery.first()
var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false val isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false
val filteredExtensions = if (query.isEmpty()) { val filteredExtensions = if (query.isEmpty()) {
availableExtensions availableExtensions
} else { } else {
@ -160,13 +159,10 @@ class MangaExtensionAdapter(private val clickListener: OnMangaInstallClickListen
} }
val extensionIconImageView: ImageView = binding.extensionIconImageView val extensionIconImageView: ImageView = binding.extensionIconImageView
fun bind(extension: MangaExtension.Available) { fun bind(extension: MangaExtension.Available) {
val nsfw = if (extension.isNsfw) { val nsfw = if (extension.isNsfw) "(18+)" else ""
"(18+)" val lang= LanguageMapper.mapLanguageCodeToName(extension.lang)
} else {
""
}
binding.extensionNameTextView.text = extension.name 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.content.pm.PackageInstaller
import android.os.Build import android.os.Build
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import ani.dantotsu.snackString
import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.extension.InstallStep
import eu.kanade.tachiyomi.util.lang.use import eu.kanade.tachiyomi.util.lang.use
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
@ -72,12 +73,18 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn
service, service,
activeSession!!.second, activeSession!!.second,
Intent(INSTALL_ACTION), 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 ).intentSender
session.commit(intentSender) session.commit(intentSender)
} }
} catch (e: Exception) { } catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" } 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) -> activeSession?.let { (_, sessionId) ->
packageInstaller.abandonSession(sessionId) packageInstaller.abandonSession(sessionId)
} }
@ -101,7 +108,7 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn
} }
init { 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 * Registers this broadcast receiver
*/ */
fun register(context: Context) { 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.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.ServiceInfo
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.IBinder import android.os.IBinder
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import ani.dantotsu.R import ani.dantotsu.R
@ -29,7 +31,11 @@ class AnimeExtensionInstallService : Service() {
setContentTitle("Installing Anime Extension...") setContentTitle("Installing Anime Extension...")
setProgress(100, 100, true) setProgress(100, 100, true)
}.build() }.build()
startForeground(Notifications.ID_EXTENSION_INSTALLER, notification) 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 { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

View file

@ -9,6 +9,7 @@ import android.content.IntentFilter
import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller
import android.os.Build import android.os.Build
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import ani.dantotsu.snackString
import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.extension.InstallStep
import eu.kanade.tachiyomi.util.lang.use import eu.kanade.tachiyomi.util.lang.use
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
@ -72,12 +73,18 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa
service, service,
activeSession!!.second, activeSession!!.second,
Intent(INSTALL_ACTION), 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 ).intentSender
session.commit(intentSender) session.commit(intentSender)
} }
} catch (e: Exception) { } catch (e: Exception) {
logcat(LogPriority.ERROR) { "Failed to install extension ${entry.downloadId} ${entry.uri}" } 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) -> activeSession?.let { (_, sessionId) ->
packageInstaller.abandonSession(sessionId) packageInstaller.abandonSession(sessionId)
} }
@ -101,7 +108,7 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa
} }
init { 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 * Registers this broadcast receiver
*/ */
fun register(context: Context) { 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.app.Service
import android.content.Context import android.content.Context
import android.content.Intent 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.net.Uri
import android.os.Build
import android.os.IBinder import android.os.IBinder
import ani.dantotsu.R import ani.dantotsu.R
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
@ -29,7 +33,11 @@ class MangaExtensionInstallService : Service() {
setContentTitle("Installing manga extension...") setContentTitle("Installing manga extension...")
setProgress(100, 100, true) setProgress(100, 100, true)
}.build() }.build()
startForeground(Notifications.ID_EXTENSION_INSTALLER, notification) 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 { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

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" <vector android:height="24dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#00000000" android:pathData="M10,12V17" <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"/>
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"/>
</vector> </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:showText="false"
app:thumbTint="@color/button_switch_track" /> app:thumbTint="@color/button_switch_track" />
<com.google.android.material.textfield.TextInputLayout
<View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="1dp"
android:layout_marginTop="16dp"> android:layout_marginStart="-16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="-16dp"
android:background="?android:attr/listDivider" />
<com.google.android.material.textfield.TextInputEditText <Button
android:id="@+id/userAgent" android:id="@+id/userAgent"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="64dp"
android:layout_marginTop="8dp" android:layout_marginStart="-32dp"
android:hint="user agent" android:layout_marginEnd="-32dp"
app:boxCornerRadiusBottomEnd="8dp" android:background="@drawable/ui_bg"
app:boxCornerRadiusBottomStart="8dp" android:backgroundTint="?attr/colorSecondary"
app:boxCornerRadiusTopEnd="8dp" android:backgroundTintMode="src_atop"
app:boxCornerRadiusTopStart="8dp" android:fontFamily="@font/poppins_bold"
app:hintAnimationEnabled="true" /> 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 <TextView
android:layout_width="match_parent" 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_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:numColumns="auto_fit" android:numColumns="auto_fit"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:columnWidth="108dp" android:columnWidth="108dp"
android:verticalSpacing="10dp" android:verticalSpacing="10dp"
android:horizontalSpacing="10dp" android:horizontalSpacing="10dp"

View file

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

View file

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

View file

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

View file

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

View file

@ -2,14 +2,102 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item <item
android:id="@+id/all" android:id="@+id/all"
android:title="All" /> android:title="All"
android:checkable="true"
android:checked="true" />
<item <item
android:id="@+id/multi" 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 <item
android:id="@+id/english" android:id="@+id/english"
android:title="English" /> android:title="English"
android:checkable="true"
android:checked="false" />
<item <item
android:id="@+id/abcd" android:id="@+id/spanish"
android:title="abcd" /> android:title="Spanish"
</menu> 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"> <style name="Theme.Dantotsu" parent="Theme.Base">
<item name="android:statusBarColor">@color/status</item> <item name="android:statusBarColor">@color/status</item>
<item name="colorOnPrimary">@color/bg_black</item> <item name="colorOnPrimary">@color/bg_black</item>

View file

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

View file

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