diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt index 0e18075b..6b61e93f 100644 --- a/app/src/main/java/ani/dantotsu/Functions.kt +++ b/app/src/main/java/ani/dantotsu/Functions.kt @@ -17,9 +17,9 @@ import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration import android.content.res.Resources +import android.content.res.Resources.getSystem import android.graphics.Bitmap import android.graphics.Color -import android.graphics.Rect import android.graphics.drawable.Drawable import android.media.MediaScannerConnection import android.net.ConnectivityManager @@ -45,15 +45,15 @@ import android.telephony.TelephonyManager import android.text.InputFilter import android.text.Spanned import android.util.AttributeSet -import android.util.DisplayMetrics import android.util.TypedValue import android.view.GestureDetector +import android.view.Gravity import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.view.ViewAnimationUtils import android.view.ViewGroup -import android.view.WindowManager +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.AlphaAnimation import android.view.animation.Animation @@ -64,10 +64,10 @@ import android.view.animation.TranslateAnimation import android.widget.ArrayAdapter import android.widget.AutoCompleteTextView import android.widget.DatePicker +import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView -import androidx.annotation.AttrRes -import androidx.annotation.ColorInt +import android.widget.Toast import androidx.appcompat.app.AppCompatDelegate import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat @@ -80,9 +80,9 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams +import androidx.core.view.updatePadding import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentManager import androidx.lifecycle.MutableLiveData import androidx.recyclerview.widget.RecyclerView @@ -91,10 +91,10 @@ import ani.dantotsu.BuildConfig.APPLICATION_ID import ani.dantotsu.connections.anilist.Genre import ani.dantotsu.connections.anilist.api.FuzzyDate import ani.dantotsu.connections.bakaupdates.MangaUpdates +import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.databinding.ItemCountDownBinding import ani.dantotsu.media.Media import ani.dantotsu.notifications.IncognitoNotificationClickReceiver -import ani.dantotsu.others.CustomBottomDialog import ani.dantotsu.others.SpoilerPlugin import ani.dantotsu.parsers.ShowResponse import ani.dantotsu.settings.saving.PrefManager @@ -120,6 +120,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.internal.ViewUtils +import com.google.android.material.snackbar.Snackbar import eu.kanade.tachiyomi.data.notification.Notifications import io.noties.markwon.AbstractMarkwonPlugin import io.noties.markwon.Markwon @@ -135,10 +136,13 @@ import io.noties.markwon.image.glide.GlideImagesPlugin import jp.wasabeef.glide.transformations.BlurTransformation import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.MainScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import nl.joery.animatedbottombar.AnimatedBottomBar +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import java.io.File import java.io.FileOutputStream import java.io.OutputStream @@ -158,30 +162,8 @@ import kotlin.math.pow var statusBarHeight = 0 var navBarHeight = 0 - -val Number.toPx get() = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics -).toInt() - -val Number.toDp get() = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_PX, this.toFloat(), Resources.getSystem().displayMetrics -) - -val Number.dpToColumns: Int get() { - val columns = currContext()?.run { - val metrics = DisplayMetrics() - with(getSystemService(Context.WINDOW_SERVICE) as WindowManager) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val bounds: Rect = currentWindowMetrics.bounds - ((bounds.width() / (resources.configuration.densityDpi / 160)) + 0.5)/ this@dpToColumns.toInt() - } else @Suppress("deprecation") { - defaultDisplay.getRealMetrics(metrics) - metrics.widthPixels.toDp / this@dpToColumns.toInt() - } - } - } ?: 1 - return columns.toInt() -} +val Int.dp: Float get() = (this / getSystem().displayMetrics.density) +val Float.px: Int get() = (this * getSystem().displayMetrics.density).toInt() lateinit var bottomBar: AnimatedBottomBar var selectedOption = 1 @@ -207,6 +189,10 @@ fun currActivity(): Activity? { var loadMedia: Int? = null var loadIsMAL = false +val Int.toPx get() = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics +).toInt() + fun initActivity(a: Activity) { val window = a.window WindowCompat.setDecorFitsSystemWindows(window, false) @@ -290,16 +276,6 @@ fun Activity.setNavigationTheme() { } } -@ColorInt -fun Context.getColorFromAttr( - @AttrRes attrColor: Int, - typedValue: TypedValue = TypedValue(), - resolveRefs: Boolean = true -): Int { - theme.resolveAttribute(attrColor, typedValue, resolveRefs) - return typedValue.data -} - /** * Sets clipToPadding false and sets the combined height of navigation bars as bottom padding. * @@ -323,48 +299,29 @@ fun ViewGroup.setBaseline(navBar: AnimatedBottomBar, overlayView: View) { setPadding(paddingLeft, paddingTop, paddingRight, navBarHeight + navBar.measuredHeight + overlayView.measuredHeight) } -/** -* Finish the calling activity and launch it again within the same lifecycle scope -*/ - fun Activity.reloadActivity() { + Refresh.all() finish() startActivity(Intent(this, this::class.java)) + initActivity(this) } -/** - * Restarts the application from the launch intent and redirects to the calling activity - */ -fun Activity.restartApp() { +fun Context.restartApp(view: View) { val mainIntent = Intent.makeRestartActivityTask( packageManager.getLaunchIntentForPackage(this.packageName)!!.component ) val component = ComponentName(this@restartApp.packageName, this@restartApp::class.qualifiedName!!) - try { - startActivity(Intent().setComponent(component)) - } catch (anything: Exception) { - startActivity(mainIntent) - } - finishAndRemoveTask() -} - -suspend fun serverDownDialog(activity: FragmentActivity?) = withContext(Dispatchers.Main) { - activity?.let { - CustomBottomDialog.newInstance().apply { - title = it.getString(R.string.anilist_broken_title) - addView(TextView(activity).apply { - text = it.getString(R.string.anilist_broken) - }) - - setNegativeButton(it.getString(R.string.cancel)) { - dismiss() + Snackbar.make(view, R.string.restart_app, Snackbar.LENGTH_INDEFINITE).apply { + setAction(R.string.do_it) { + this.dismiss() + try { + startActivity(Intent().setComponent(component)) + } catch (anything: Exception) { + startActivity(mainIntent) } - - setPositiveButton(it.getString(R.string.close)) { - it.finishAffinity() - } - show(it.supportFragmentManager, "dialog") + Runtime.getRuntime().exit(0) } + show() } } @@ -440,13 +397,17 @@ fun isOnline(context: Context): Boolean { fun startMainActivity(activity: Activity, bundle: Bundle? = null) { activity.finishAffinity() activity.startActivity( - Intent(activity, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK + Intent( + activity, + MainActivity::class.java + ).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) if (bundle != null) putExtras(bundle) } ) } + class DatePickerFragment(activity: Activity, var date: FuzzyDate = FuzzyDate().getToday()) : DialogFragment(), DatePickerDialog.OnDateSetListener { @@ -644,6 +605,11 @@ fun MutableList.sortByTitle(string: String) { } } +fun String.findBetween(a: String, b: String): String? { + val string = substringAfter(a, "").substringBefore(b, "") + return string.ifEmpty { null } +} + fun ImageView.loadImage(url: String?, size: Int = 0) { if (!url.isNullOrEmpty()) { val localFile = File(url) @@ -655,13 +621,8 @@ fun ImageView.loadImage(url: String?, size: Int = 0) { } } -fun geUrlOrTrolled(url: String?) : String { - return if (PrefManager.getVal(PrefName.DisableMitM)) url ?: "" else - PrefManager.getVal(PrefName.ImageUrl).ifEmpty { url ?: "" } -} - fun ImageView.loadImage(file: FileUrl?, size: Int = 0) { - file?.url = geUrlOrTrolled(file?.url) + file?.url = PrefManager.getVal(PrefName.ImageUrl).ifEmpty { file?.url ?: "" } if (file?.url?.isNotEmpty() == true) { tryWith { if (file.url.startsWith("content://")) { @@ -1164,6 +1125,68 @@ class EmptyAdapter(private val count: Int) : RecyclerView.Adapter { + gravity = (Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM) + width = WRAP_CONTENT + } + translationY = -(navBarHeight.dp + 32f) + translationZ = 32f + updatePadding(16f.px, right = 16f.px) + setOnClickListener { + snackBar.dismiss() + } + setOnLongClickListener { + copyToClipboard(clipboard ?: s, false) + toast(getString(R.string.copied_to_clipboard)) + true + } + } + snackBar.show() + } + return snackBar + } + Logger.log(s) + } + } catch (e: Exception) { + Logger.log(e) + Injekt.get().logException(e) + } + return null +} + +fun snackString(r: Int, activity: Activity? = null, clipboard: String? = null): Snackbar? { + return snackString(getAppString(r), activity, clipboard) +} + open class NoPaddingArrayAdapter(context: Context, layoutId: Int, items: List) : ArrayAdapter(context, layoutId, items) { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { @@ -1328,12 +1351,12 @@ fun openSettings(context: Context, channelId: String?): Boolean { } suspend fun View.pop() { - withContext(Dispatchers.Main) { + currActivity()?.runOnUiThread { ObjectAnimator.ofFloat(this@pop, "scaleX", 1f, 1.25f).setDuration(120).start() ObjectAnimator.ofFloat(this@pop, "scaleY", 1f, 1.25f).setDuration(120).start() } delay(120) - withContext(Dispatchers.Main) { + currActivity()?.runOnUiThread { ObjectAnimator.ofFloat(this@pop, "scaleX", 1.25f, 1f).setDuration(100).start() ObjectAnimator.ofFloat(this@pop, "scaleY", 1.25f, 1f).setDuration(100).start() } @@ -1347,7 +1370,7 @@ fun blurImage(imageView: ImageView, banner: String?) { if (PrefManager.getVal(PrefName.BlurBanners)) { val context = imageView.context if (!(context as Activity).isDestroyed) { - val url = geUrlOrTrolled(banner) + val url = PrefManager.getVal(PrefName.ImageUrl).ifEmpty { banner } Glide.with(context as Context) .load( if (banner.startsWith("http")) GlideUrl(url) else if (banner.startsWith("content://")) Uri.parse( @@ -1355,11 +1378,7 @@ fun blurImage(imageView: ImageView, banner: String?) { ) else File(url) ) .diskCacheStrategy(DiskCacheStrategy.RESOURCE).override(400) - .apply(if (PrefManager.getVal(PrefName.ImageUrl).isEmpty()) { - RequestOptions.noTransformation() - } else { - RequestOptions.bitmapTransform(BlurTransformation(radius, sampling)) - }) + .apply(RequestOptions.bitmapTransform(BlurTransformation(radius, sampling))) .into(imageView) } } else { diff --git a/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt b/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt index c2e59000..a02214e3 100644 --- a/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt +++ b/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt @@ -5,7 +5,6 @@ import ani.dantotsu.R import ani.dantotsu.client import ani.dantotsu.media.Media import ani.dantotsu.tryWithSuspend -import ani.dantotsu.utf8 import ani.dantotsu.util.Logger import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -15,6 +14,8 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.json.JSONException import org.json.JSONObject +import java.net.URLEncoder +import java.nio.charset.Charset import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale @@ -23,6 +24,8 @@ import java.util.concurrent.TimeUnit class MangaUpdates { + val String.utf8: String get() = URLEncoder.encode(this, Charset.forName("UTF-8").name()) + private val Int?.dateFormat get() = String.format("%02d", this) suspend fun findLatestRelease(media: Media) : ReleaseResponse.Results? { @@ -123,32 +126,38 @@ class MangaUpdates { suspend fun predictRelease(media: Media, latest: Long): Long? { val releaseDates = findReleaseDates(media) - if (releaseDates.size < 3) return null + if (releaseDates.size < 5) return null releaseDates.forEach { Logger.log(it) } - val dateLatest = getCalendarInstance(releaseDates[0]) - val dateMiddle = getCalendarInstance(releaseDates[1]) - val dateOldest = getCalendarInstance(releaseDates[2]) - val daysNew: Long = TimeUnit.MILLISECONDS.toDays(dateLatest.timeInMillis - dateMiddle.timeInMillis) - val daysOld: Long = TimeUnit.MILLISECONDS.toDays(dateMiddle.timeInMillis - dateOldest.timeInMillis) + val date01 = getCalendarInstance(releaseDates[0]) + val date02 = getCalendarInstance(releaseDates[1]) + val date03 = getCalendarInstance(releaseDates[2]) + val date04 = getCalendarInstance(releaseDates[3]) + val date05 = getCalendarInstance(releaseDates[4]) + val days0102: Long = TimeUnit.MILLISECONDS.toDays(date01.timeInMillis - date02.timeInMillis) + val days0203: Long = TimeUnit.MILLISECONDS.toDays(date02.timeInMillis - date03.timeInMillis) + val days0304: Long = TimeUnit.MILLISECONDS.toDays(date03.timeInMillis - date04.timeInMillis) + val days0405: Long = TimeUnit.MILLISECONDS.toDays(date04.timeInMillis - date05.timeInMillis) + + val average = (days0102 + days0203 + days0304 + days0405) / 4 val date: Calendar = Calendar.getInstance() date.timeInMillis = latest return when { - daysNew in 5..14 && daysOld in 5..14 -> { + average in 5..14 -> { latest + 604800000 // 7 days } - daysNew in 28..36 && daysOld in 28..36 -> { + average in 28..36 -> { date.add(Calendar.MONTH, 1) date.timeInMillis } - daysNew in 84..98 && daysOld in 84..98 -> { + average in 84..98 -> { date.add(Calendar.MONTH, 3) date.timeInMillis } - daysNew >= 358 && daysOld >= 358 -> { + average >= 358 -> { date.add(Calendar.YEAR, 1) date.timeInMillis } @@ -238,4 +247,4 @@ class MangaUpdates { val asString: String? ) } -} +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt index 72e6f546..2f1705a2 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt @@ -35,10 +35,10 @@ import ani.dantotsu.others.webview.CookieCatcher import ani.dantotsu.parsers.DynamicMangaParser import ani.dantotsu.parsers.MangaReadSources import ani.dantotsu.parsers.MangaSources +import ani.dantotsu.px import ani.dantotsu.settings.FAQActivity import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName -import ani.dantotsu.sinceWhen import ani.dantotsu.toast import com.google.android.material.chip.Chip import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK @@ -53,6 +53,7 @@ class MangaReadAdapter( private val fragment: MangaReadFragment, private val mangaReadSources: MangaReadSources ) : RecyclerView.Adapter() { + var subscribe: MediaDetailsActivity.PopImageButton? = null private var _binding: ItemAnimeWatchBinding? = null val hiddenScanlators = mutableListOf() @@ -228,7 +229,7 @@ class MangaReadAdapter( refresh = true val intent = Intent(fragment.requireContext(), CookieCatcher::class.java) .putExtra("url", url) - startActivity(fragment.requireContext(), intent, null) + ContextCompat.startActivity(fragment.requireContext(), intent, null) } } } @@ -366,7 +367,7 @@ class MangaReadAdapter( fun updateChips(limit: Int, names: Array, arr: Array, selected: Int = 0) { val binding = _binding if (binding != null) { - val screenWidth = fragment.resources.displayMetrics.widthPixels + val screenWidth = fragment.screenWidth.px var select: Chip? = null for (position in arr.indices) { val last = if (position + 1 == arr.size) names.size else (limit * (position + 1)) @@ -484,8 +485,9 @@ class MangaReadAdapter( binding.animeSourceContinue.visibility = View.GONE } binding.animeSourceProgressBar.visibility = View.GONE - val sourceFound = media.manga.chapters!!.isNotEmpty() + binding.animeSourceNotFound.isGone = sourceFound + binding.faqbutton.isGone = sourceFound if (!sourceFound && PrefManager.getVal(PrefName.SearchSources)) { if (binding.animeSource.adapter.count > media.selected!!.sourceIndex + 1) { val nextIndex = media.selected!!.sourceIndex + 1 @@ -502,8 +504,6 @@ class MangaReadAdapter( fragment.loadChapters(nextIndex, invalidate) } } - binding.animeSourceNotFound.isGone = sourceFound - binding.faqbutton.isGone = sourceFound } else { binding.animeSourceContinue.visibility = View.GONE binding.animeSourceNotFound.visibility = View.GONE @@ -523,19 +523,16 @@ class MangaReadAdapter( ext.sourceLanguage = lang } try { - binding?.animeSourceLanguage?.setText( - LanguageMapper.getExtensionItem(parser.extension.sources[lang])) + binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang) } catch (e: IndexOutOfBoundsException) { binding?.animeSourceLanguage?.setText( - parser.extension.sources.firstOrNull()?.let { - LanguageMapper.getExtensionItem(it) - } ?: "Unknown" + parser.extension.sources.firstOrNull()?.lang ?: "Unknown" ) } val adapter = ArrayAdapter( fragment.requireContext(), R.layout.item_dropdown, - parser.extension.sources.map { LanguageMapper.getExtensionItem(it) } + parser.extension.sources.map { LanguageMapper.mapLanguageCodeToName(it.lang) } ) val items = adapter.count binding?.animeSourceLanguageContainer?.isVisible = items > 1 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 38b8929c..e4206ef6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,13 +1,23 @@ + rebelonion/Dantotsu + dantotsuprefs + + Dantotsu The NEW Best Anime & Manga app for Android. - Sign In + Login Logout - Welcome back! - It appears you have an older package installed.\nPlease select \"Backup\" to open the older version and perform a backup. You can then return to this app and use \"Restore Settings\". - Backup + https://dantotsu.app/ + https://discord.gg/4HPZ5nAWwM + https://github.com/rebelonion/Dantotsu + https://t.me/+gzBCQExtLQo1YTNh + https://www.buymeacoffee.com/rebelonion + + https://anilist.co/user/%1$s/ + https://myanimelist.net/profile/%1$s/ + https://discord.com/users/%1$s/ Home Anime @@ -29,7 +39,6 @@ " : " No Internet Connection - No Internet Connection\nOffline mode available Refresh Search @@ -46,10 +55,11 @@ Username Chapters Read + Chapters\nRead Episodes Watched + Episodes\nWatched Continue Reading Continue Watching - Continue… Recommended Watch/Read some Anime or Manga to get Recommendations @@ -73,12 +83,8 @@ All - Use foldable layouts - Add shortcuts to launcher icon - No more notifications Followers - Show social stats in media STATUS @@ -168,19 +174,6 @@ Prequel Sequel - TorrServer - Server is running… - Internal TorrServer - Server port number - torrents - Active torrents - Remove this torrent? - Invalid port entered! - Port must be a valid TCP port (0 – 65535) - TorrServer in disabled! - Starting TorrServer - Would you like to temporarily enable TorrServer (disabled on app close)? - Anilist Settings Extensions Downloads @@ -189,7 +182,7 @@ Extensions Extension updates available Player Settings - Only my content in \"Recently Updated\" + Only show my content in \"Recently Updated\" Download Manager Download in SD card No SD card was Found. @@ -201,13 +194,10 @@ User Interface Common Theme - Theme / UI - Light / Dark Theme UI Settings - System About " Dantotsu is crafted from the ashes of Saikou and based on simplistic yet state-of-the-art elegance. It is an Anilist only client, which also lets you stream-download Anime through extensions & Manga.\nDantotsu literally means the \"best of the best\" in japanese. Well, we would like to say this is the best open source app for anime and manga on Android, what would you say?" - Contributors + Developers/Helpers Disclaimer - Dantotsu by itself only provides an anime and manga tracker and does not provide any anime or manga streaming or downloading capabilities. @@ -265,7 +255,6 @@ Example Sub Subtitle Font Subtitle Size - No Subtitles Available Auto Autoplay Next Episode @@ -287,7 +276,7 @@ The percentage at which your Anilist progress should be updated after watching an episode. \nThis also sets the \% for when to preload links for the next episode. Behaviour - Always resume from timestamp + Always Continue from where you left off Pause when not in Focus Volume & Brightness Gestures Double tap to Seek @@ -343,10 +332,6 @@ Spaced Pages Direction - Comments API (Private) - - Prevent Injection (\"Pranks\") - General Show Status & Navigation Bars Auto Detect Webtoon @@ -373,7 +358,7 @@ Other TOTAL REPEATS Custom Lists - Want to support Mr. Matagi?\nConsider Donating + Want to support Dantotsu\'s Maintainer?\nConsider Donating No donation goal atm Filter Year @@ -387,8 +372,8 @@ Calendar Planned Anime Planned Manga - Long click to open image - Continue previously opened items + Open image by Long Clicking + Always continue previous items Search next available source Useful if you are getting Handshake Fails Use Proxy for Timestamps @@ -398,7 +383,7 @@ FAQ Accounts MyAnimeList - Log in with Anilist + Login with Anilist! Anilist How does this work\? @@ -417,15 +402,15 @@ \n\n_It is not required to sync both MAL and Anilist accounts._ - Show notification for checking subscriptions + Show notification for Checking Subscriptions Use Alarm Manager - Use Alarm Manager (Reliable Notifications) + Use Alarm Manager for reliable Notifications Using Alarm Manger can help fight against battery optimization, but may consume more battery. It also requires the Alarm Manager permission. Use - Subscription Check Notifications + Notification for Checking Subscriptions Subscriptions Update Frequency : %1$s Subscriptions Update Frequency - Amount of time for Dantotsu to check for new episodes / chapters\n(Less time consumes more battery) + Amount of time for Dantotsu to periodically check for new Episodes/Chapters\n(Less time will cause more battery consumption) Don\'t Update Loading Chapter %1$s Sort by Release Date @@ -442,12 +427,6 @@ Step: %1$s Review - Select a Source - - Dantotsu update %1$s - Install update %1$s? - Update permission denied! - Display only the first button Display dantotsu in the second button Display your AniList profile instead @@ -460,18 +439,19 @@ Error loading data %1$s Long click to check for app updates Saved to:\n%s - ✔ [%1$s] %2$d - Please log into AniList account! + Setting progress to %1$d + Please Login into AniList account! Congrats Vro Please Reload. Copied "%1$s" Press BACK again to exit + No Internet Connection Seems like that wasn\'t found on Anilist. Disabled Auto Skipping OP & ED Auto Skipping OP & ED - Show Skip [Segment] Buttons + Show Skip Time Stamp Button Always Load Time Stamps - >Auto Hide Skip [Segment] Buttons + Auto Hide Time Stampsstring Segments Auto Skip OP / ED Requires Time Stamps to be Enabled @@ -486,7 +466,7 @@ Getting User Data No next episode found! Try enabling \"Banner Animations\" in settings - Please log in with Anilist! + Please Login with Anilist! Auto Update progress has now been reset-ed Can\'t wait, huh? fine X( Downloading… @@ -503,15 +483,10 @@ List Updated Deleted from List No List ID found… - - Mr. Matagi Update %1$s - Don\'t notify again for %1$s - Downloading Mr. Matagi %1$s - Checking for Update - Don\'t notify again for version %1$s + Don\'t show again for version %1$s No Update Found - Downloading Dantotsu %1$s + Downloading Update %1$s Please give permission to access Files & Folders from Settings, & Try again. Started Downloading\n%1$s Please install 1DM @@ -636,7 +611,7 @@ Some mentionable features of Dantotsu are\n\n- Easy and functional way to both, watch anime and read manga and light novels, Ad Free.\n- A completely open source app with a nice UI & Animations\n- 3rd party plugin support \n- Synchronize anime and manga real-time with AniList. Easily categorize anime and manga based on your current status. (Powered by AniList)\n- Find all shows using thoroughly and frequently updated list of all trending, popular and ongoing anime based on scores.\n- View extensive details about anime shows, movies and manga titles. It also features ability to countdown to the next episode of airing anime. (Powered by AniList & MyAnimeList) Whats the difference between Stable, Beta & Alpha versions? - This fork does not provide separate tracks. The version you download from the [repository](https://github.com/RepoDevil/Mr.Matagi) is the same one [AbandonedCart](https://github.com/AbandonedCart) is running. If you find bugs and have already updated to the latest version, feel free to submit an [issue](https://github.com/RepoDevil/Mr.Matagi/issues) + A Stable release is a version that has been tested as thoroughly as possible and is as reliable as we can make it.\n\nA Beta release is a version which is meant for testing new features or providing hot fixes.\n\nAn Alpha release is like a beta version but has many bugs and you can only find it on our [discord](https://discord.gg/invite/4HPZ5nAWwM) server. It gets frequent updates and has a high chance to break.\n\nIf you want a reliable app then go for the Stable. If you want the latest and greatest features and bugs then go for Alpha. Is Dantotsu available for PC? Currently no (for both Windows and Linux). There isn\'t any estimation when it will be available. But you can download any Android emulator and run Dantotsu on it. For Windows 11 users, they can use the Windows Subsystem for Android (WSA) to run Dantotsu in Windows. @@ -722,7 +697,7 @@ Theme: User Agent Custom Theme: - Custom Theme + Custom theme Theme as Anime/Manga OLED theme variant Installed Anime @@ -782,7 +757,6 @@ Please wait Upcoming No shows to display - No media to display Extension Name version Enter your password to decrypt the file @@ -801,6 +775,14 @@ Set Cookies Open Website + + +Lorem ipsum dolor sit amet. Est consectetur sint qui internos optio nam Quis excepturi qui voluptatem animi. Qui labore quasi vel suscipit deleniti et doloremque omnis in velit suscipit et quasi eaque. Et doloribus recusandae id laudantium Quis qui natus velit in voluptatem voluptatem! + +Et magni quasi vel nemo omnis et voluptate quisquam vel corporis fuga ut consequatur voluptas At quis veniam. At assumenda illum id minus veritatis id consequatur ipsum est quod corrupti quo adipisci sint. Quo explicabo doloribus et excepturi internos est reiciendis laboriosam ut explicabo veniam ut culpa mollitia in ducimus sint aut autem voluptatem! In consectetur laudantium non omnis saepe nam sint fuga. + +Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exercitationem adipisci quo nemo aliquam ea numquam beatae. Eum Quis dolore aut quia accusantium sed vero autem vel quaerat eaque et beatae dicta non delectus galisum non ullam nulla. + Log to File Logging to a file will slow down the app. Only enable if you are experiencing issues. Radius @@ -821,6 +803,8 @@ Download Manager Enter Password + youwu have been cuwsed :pwayge: + https://www.youtube.com/watch?v=dQw4w9WgXcQ Are you sure you want to purge all %1$s downloads? Failed to delete because of… %1$s @@ -855,19 +839,19 @@ Restore Backup No location selected + Enjoying the App? + Consider donating! + no moners :( + That\'s alright, you\'ll be a rich man soon :prayge: + donate :) Do it! Password - Internal Server Error! - AniList appears to be unresponsive and functionality will be severely limited. Would you like to close the app and try again later?\n - Search %1$s Track progress directly from your home screen - Anime - Manga - Chapters - Episodes + Anime\nWatched + Manga\nRead Loading… %1$s\'s Stats @@ -875,17 +859,11 @@ log in or join - Audio Tracks - \[💬\] Disabled - \[⁉️\] Invalid - \[%1$s\] Unknown - Top background color Bottom Background Color Countdown Text Color Title Color Stats Text Color - Flipper Color Placeholder Add Anime Repo @@ -900,18 +878,13 @@ Trending Manhwa Liked By Adult only content - Report - Ban - - Activity - Your path could not be set Downloads access Please choose a directory to save your downloads - Download Subtitle Change Download Location Are you sure you want to change the download location?\nOld downloads may no longer be accessible. - + Report + Ban Voice Actors Permission is required to download Media @@ -919,18 +892,16 @@ Social Auto Skip Recap Use AniList Icon - - Source Exception: %1$s - Decoding failed: %1$s - Player Error: %1$d %2$s: %3$s - + Audio Tracks + Disabled + Invalid + \[%1$s\] Unknown Anilist, MAL and Discord.\nWhat more could you need? Change the vibe of your app - Manage your repo collection - Downloads, DNS, and defaults + Manage your reliable repositories + UI and other mischievous stuff + Customise your news and updates Choose how you watch Choose how you read - Customize news and updates - Updates and useful utilities - Learn more about Mr. Matagi + Learn more about Dantotsu