Compare commits

..

No commits in common. "a93b4f5b1102f781fe2b1b1e51adacf2d83fdb71" and "f606bef2a5199d0af8ae0d26b6299defe8946091" have entirely different histories.

19 changed files with 1324 additions and 1553 deletions

View file

@ -14,7 +14,7 @@ Dantotsu is an [Anilist](https://anilist.co/) only client.
> **Dantotsu (断トツ; Dan-totsu)** literally means "the best of the best" in Japanese. Try it out for yourself and be the judge!
<a href="https://www.buymeacoffee.com/rebelonion"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=rebelonion&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" /></a>
<a href="https://www.buymeacoffee.com/rebelonion"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=rebelonion&button_colour=FFDD00&font_colour=030201&font_family=Poppins&outline_colour=000000&coffee_colour=ffffff" /></a>
## Terms of Use
By downloading, installing, or using this application, you agree to:

View file

@ -17,8 +17,9 @@ android {
applicationId "ani.dantotsu"
minSdk 21
targetSdk 35
versionName "3.2.2"
versionCode 300200200
versionCode((System.currentTimeMillis() / 60000).toInteger())
versionName "3.2.0"
versionCode 300200000
signingConfig signingConfigs.debug
}

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

View file

@ -253,7 +253,7 @@ data class MediaStreamingEpisode(
// The site location of the streaming episode
@SerialName("site") var site: String?,
) : java.io.Serializable
)
@Serializable
data class MediaCoverImage(

View file

@ -50,8 +50,7 @@ open class RPC(val token: String, val coroutineContext: CoroutineContext) {
val assetApi = RPCExternalAsset(data.applicationId, token!!, client, json)
suspend fun String.discordUrl() = assetApi.getDiscordUri(this)
return json.encodeToString(
Presence.Response(
return json.encodeToString(Presence.Response(
3,
Presence(
activities = listOf(

View file

@ -232,18 +232,12 @@ class MangaDownloaderService : Service() {
image.page,
image.source
)
if (bitmap == null) {
snackString("${task.chapter} - Retrying to download page ${index.ofLength(3)}, attempt ${retryCount + 1}.")
}
retryCount++
}
if (bitmap == null) {
outputDir.deleteRecursively(this@MangaDownloaderService, false)
throw Exception("${task.chapter} - Unable to download all pages after $retryCount attempts. Try again.")
}
if (bitmap != null) {
saveToDisk("${index.ofLength(3)}.jpg", outputDir, bitmap)
}
farthest++
builder.setProgress(task.imageData.size, farthest, false)

File diff suppressed because it is too large Load diff

View file

@ -7,11 +7,9 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.EditText
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.NumberPicker
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getString
import androidx.core.content.ContextCompat.startActivity
@ -267,22 +265,19 @@ class MangaReadAdapter(
}
// Multi download
//downloadNo.text = "0"
downloadNo.text = "0"
mediaDownloadTop.setOnClickListener {
// Alert dialog asking for the number of chapters to download
fragment.requireContext().customAlertDialog().apply {
setTitle("Multi Chapter Downloader")
setMessage("Enter the number of chapters to download")
val input = View.inflate(currContext(), R.layout.dialog_layout, null)
val editText = input.findViewById<EditText>(R.id.downloadNo)
val input = NumberPicker(currContext())
input.minValue = 1
input.maxValue = 20
input.value = 1
setCustomView(input)
setPosButton(R.string.ok) {
val value = editText.text.toString().toIntOrNull()
if (value != null && value > 0) {
downloadNo.setText(value.toString(), TextView.BufferType.EDITABLE)
fragment.multiDownload(value)
} else {
toast("Please enter a valid number")
}
downloadNo.text = "${input.value}"
}
setNegButton(R.string.cancel)
show()
@ -387,9 +382,8 @@ class MangaReadAdapter(
setCustomView(root)
setPosButton("OK") {
if (run) fragment.onIconPressed(style, reversed)
val value = downloadNo.text.toString().toIntOrNull()
if (value != null && value > 0) {
fragment.multiDownload(value)
if (downloadNo.text != "0") {
fragment.multiDownload(downloadNo.text.toString().toInt())
}
if (refresh) fragment.loadChapters(source, true)
}

View file

@ -474,7 +474,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
scanlator = chapter.scanlator ?: "Unknown",
imageData = images,
sourceMedia = media,
retries = 25,
retries = 2,
simultaneousDownloads = 2
)

View file

@ -24,11 +24,11 @@ class CrashActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme()
initActivity(this)
binding = ActivityCrashBinding.inflate(layoutInflater)
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
binding = ActivityCrashBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = statusBarHeight

View file

@ -19,7 +19,6 @@ import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.util.customAlertDialog
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -58,16 +57,23 @@ class SettingsAnimeActivity : AppCompatActivity() {
desc = getString(R.string.purge_anime_downloads_desc),
icon = R.drawable.ic_round_delete_24,
onClick = {
context.customAlertDialog().apply {
setTitle(R.string.purge_anime_downloads)
setMessage(R.string.purge_confirm, getString(R.string.anime))
setPosButton(R.string.yes, onClick = {
val dialog = AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.purge_anime_downloads)
.setMessage(
getString(
R.string.purge_confirm,
getString(R.string.anime)
)
)
.setPositiveButton(R.string.yes) { dialog, _ ->
val downloadsManager = Injekt.get<DownloadsManager>()
downloadsManager.purgeDownloads(MediaType.ANIME)
})
setNegButton(R.string.no)
show()
}
dialog.dismiss()
}.setNegativeButton(R.string.no) { dialog, _ ->
dialog.dismiss()
}.create()
dialog.window?.setDimAmount(0.8f)
dialog.show()
}
),

View file

@ -45,6 +45,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.UUID
class SettingsCommonActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingsCommonBinding
private lateinit var launcher: LauncherWrapper
@ -61,22 +62,18 @@ class SettingsCommonActivity : AppCompatActivity() {
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
if (uri != null) {
try {
val jsonString =
contentResolver.openInputStream(uri)?.readBytes()
val jsonString = contentResolver.openInputStream(uri)?.readBytes()
?: throw Exception("Error reading file")
val name = DocumentFile.fromSingleUri(this, uri)?.name ?: "settings"
// .sani is encrypted, .ani is not
//.sani is encrypted, .ani is not
if (name.endsWith(".sani")) {
passwordAlertDialog(false) { password ->
if (password != null) {
val salt = jsonString.copyOfRange(0, 16)
val encrypted = jsonString.copyOfRange(16, jsonString.size)
val decryptedJson =
try {
val decryptedJson = try {
PreferenceKeystore.decryptWithPassword(
password,
encrypted,
salt,
password, encrypted, salt
)
} catch (e: Exception) {
toast(getString(R.string.incorrect_password))
@ -103,6 +100,7 @@ class SettingsCommonActivity : AppCompatActivity() {
launcher = LauncherWrapper(this, contract)
binding.apply {
settingsCommonLayout.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = statusBarHeight
bottomMargin = navBarHeight
@ -110,8 +108,7 @@ class SettingsCommonActivity : AppCompatActivity() {
commonSettingsBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
val exDns =
listOf(
val exDns = listOf(
"None",
"Cloudflare",
"Google",
@ -125,15 +122,13 @@ class SettingsCommonActivity : AppCompatActivity() {
"Controld",
"Njalla",
"Shecan",
"Libre",
"Libre"
)
settingsExtensionDns.setText(exDns[PrefManager.getVal(PrefName.DohProvider)])
settingsExtensionDns.setAdapter(
ArrayAdapter(
context,
R.layout.item_dropdown,
exDns,
),
context, R.layout.item_dropdown, exDns
)
)
settingsExtensionDns.setOnItemClickListener { _, _, i, _ ->
PrefManager.setVal(PrefName.DohProvider, i)
@ -141,8 +136,7 @@ class SettingsCommonActivity : AppCompatActivity() {
restartApp()
}
settingsRecyclerView.adapter =
SettingsAdapter(
settingsRecyclerView.adapter = SettingsAdapter(
arrayListOf(
Settings(
type = 1,
@ -153,11 +147,21 @@ class SettingsCommonActivity : AppCompatActivity() {
startActivity(
Intent(
context,
UserInterfaceSettingsActivity::class.java,
),
UserInterfaceSettingsActivity::class.java
)
)
},
isActivity = true,
isActivity = true
),
Settings(
type = 2,
name = getString(R.string.open_animanga_directly),
desc = getString(R.string.open_animanga_directly_info),
icon = R.drawable.ic_round_search_24,
isChecked = PrefManager.getVal(PrefName.AniMangaSearchDirect),
switch = { isChecked, _ ->
PrefManager.setVal(PrefName.AniMangaSearchDirect, isChecked)
}
),
Settings(
type = 1,
@ -170,13 +174,13 @@ class SettingsCommonActivity : AppCompatActivity() {
setTitle(getString(R.string.download_manager))
singleChoiceItems(
managers,
PrefManager.getVal(PrefName.DownloadManager),
PrefManager.getVal(PrefName.DownloadManager)
) { count ->
PrefManager.setVal(PrefName.DownloadManager, count)
}
show()
}
},
}
),
Settings(
type = 1,
@ -193,26 +197,21 @@ class SettingsCommonActivity : AppCompatActivity() {
PrefManager.setVal(PrefName.OverridePassword, true)
}
val password = view.passwordInput.text.toString()
val confirmPassword =
view.confirmPasswordInput.text.toString()
val confirmPassword = view.confirmPasswordInput.text.toString()
if (password == confirmPassword && password.isNotEmpty()) {
PrefManager.setVal(PrefName.AppPassword, password)
if (view.biometricCheckbox.isChecked) {
val canBiometricPrompt =
BiometricManager
.from(applicationContext)
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) ==
BiometricManager.BIOMETRIC_SUCCESS
BiometricManager.from(applicationContext)
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
if (canBiometricPrompt) {
val biometricPrompt =
BiometricPromptUtils.createBiometricPrompt(
this@SettingsCommonActivity
) { _ ->
BiometricPromptUtils.createBiometricPrompt(this@SettingsCommonActivity) { _ ->
val token = UUID.randomUUID().toString()
PrefManager.setVal(
PrefName.BiometricToken,
token,
token
)
toast(R.string.success)
}
@ -220,6 +219,7 @@ class SettingsCommonActivity : AppCompatActivity() {
BiometricPromptUtils.createPromptInfo(this@SettingsCommonActivity)
biometricPrompt.authenticate(promptInfo)
}
} else {
PrefManager.setVal(PrefName.BiometricToken, "")
toast(R.string.success)
@ -238,20 +238,19 @@ class SettingsCommonActivity : AppCompatActivity() {
setOnShowListener {
view.passwordInput.requestFocus()
val canAuthenticate =
BiometricManager.from(applicationContext)
.canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_WEAK,
BiometricManager.from(applicationContext).canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_WEAK
) == BiometricManager.BIOMETRIC_SUCCESS
view.biometricCheckbox.isVisible = canAuthenticate
view.biometricCheckbox.isChecked =
PrefManager.getVal(PrefName.BiometricToken, "")
.isNotEmpty()
PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty()
view.forgotPasswordCheckbox.isChecked =
PrefManager.getVal(PrefName.OverridePassword)
}
show()
}
},
}
),
Settings(
type = 1,
@ -260,26 +259,24 @@ class SettingsCommonActivity : AppCompatActivity() {
icon = R.drawable.backup_restore,
onClick = {
StoragePermissions.downloadsPermission(context)
val selectedArray = mutableListOf(false)
val filteredLocations = Location.entries.filter { it.exportable }
val selectedArray = BooleanArray(filteredLocations.size) { false }
context.customAlertDialog().apply {
setTitle(R.string.backup_restore)
multiChoiceItems(
selectedArray.addAll(List(filteredLocations.size - 1) { false })
val dialog = AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.backup_restore).setMultiChoiceItems(
filteredLocations.map { it.name }.toTypedArray(),
selectedArray,
) { updatedSelection ->
for (i in updatedSelection.indices) {
selectedArray[i] = updatedSelection[i]
}
}
setPosButton(R.string.button_restore) {
selectedArray.toBooleanArray()
) { _, which, isChecked ->
selectedArray[which] = isChecked
}.setPositiveButton(R.string.button_restore) { dialog, _ ->
openDocumentLauncher.launch(arrayOf("*/*"))
}
setNegButton(R.string.button_backup) {
dialog.dismiss()
}.setNegativeButton(R.string.button_backup) { dialog, _ ->
if (!selectedArray.contains(true)) {
toast(R.string.no_location_selected)
return@setNegButton
return@setNegativeButton
}
dialog.dismiss()
val selected =
filteredLocations.filterIndexed { index, _ -> selectedArray[index] }
if (selected.contains(Location.Protected)) {
@ -289,7 +286,7 @@ class SettingsCommonActivity : AppCompatActivity() {
"DantotsuSettings",
PrefManager.exportAllPrefs(selected),
context,
password,
password
)
} else {
toast(R.string.password_cannot_be_empty)
@ -300,13 +297,14 @@ class SettingsCommonActivity : AppCompatActivity() {
"DantotsuSettings",
PrefManager.exportAllPrefs(selected),
context,
null,
null
)
}
}
setNeutralButton(R.string.cancel) {}
show()
}
}.setNeutralButton(R.string.cancel) { dialog, _ ->
dialog.dismiss()
}.create()
dialog.window?.setDimAmount(0.8f)
dialog.show()
},
),
Settings(
@ -319,8 +317,7 @@ class SettingsCommonActivity : AppCompatActivity() {
setTitle(R.string.change_download_location)
setMessage(R.string.download_location_msg)
setPosButton(R.string.ok) {
val oldUri =
PrefManager.getVal<String>(PrefName.DownloadsDir)
val oldUri = PrefManager.getVal<String>(PrefName.DownloadsDir)
launcher.registerForCallback { success ->
if (success) {
toast(getString(R.string.please_wait))
@ -328,9 +325,7 @@ class SettingsCommonActivity : AppCompatActivity() {
PrefManager.getVal<String>(PrefName.DownloadsDir)
GlobalScope.launch(Dispatchers.IO) {
Injekt.get<DownloadsManager>().moveDownloadsDir(
context,
Uri.parse(oldUri),
Uri.parse(newUri),
context, Uri.parse(oldUri), Uri.parse(newUri)
) { finished, message ->
if (finished) {
toast(getString(R.string.success))
@ -348,7 +343,7 @@ class SettingsCommonActivity : AppCompatActivity() {
setNegButton(R.string.cancel)
show()
}
},
}
),
Settings(
type = 2,
@ -358,7 +353,7 @@ class SettingsCommonActivity : AppCompatActivity() {
isChecked = PrefManager.getVal(PrefName.ContinueMedia),
switch = { isChecked, _ ->
PrefManager.setVal(PrefName.ContinueMedia, isChecked)
},
}
),
Settings(
type = 2,
@ -369,7 +364,7 @@ class SettingsCommonActivity : AppCompatActivity() {
switch = { isChecked, _ ->
PrefManager.setVal(PrefName.HidePrivate, isChecked)
restartApp()
},
}
),
Settings(
type = 2,
@ -379,7 +374,7 @@ class SettingsCommonActivity : AppCompatActivity() {
isChecked = PrefManager.getVal(PrefName.SearchSources),
switch = { isChecked, _ ->
PrefManager.setVal(PrefName.SearchSources, isChecked)
},
}
),
Settings(
type = 2,
@ -389,7 +384,7 @@ class SettingsCommonActivity : AppCompatActivity() {
isChecked = PrefManager.getVal(PrefName.RecentlyListOnly),
switch = { isChecked, _ ->
PrefManager.setVal(PrefName.RecentlyListOnly, isChecked)
},
}
),
Settings(
type = 2,
@ -401,27 +396,23 @@ class SettingsCommonActivity : AppCompatActivity() {
PrefManager.setVal(PrefName.AdultOnly, isChecked)
restartApp()
},
isVisible = Anilist.adult,
),
isVisible = Anilist.adult
),
)
)
settingsRecyclerView.apply {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
setHasFixedSize(true)
}
var previousStart: View =
when (PrefManager.getVal<Int>(PrefName.DefaultStartUpTab)) {
var previousStart: View = when (PrefManager.getVal<Int>(PrefName.DefaultStartUpTab)) {
0 -> uiSettingsAnime
1 -> uiSettingsHome
2 -> uiSettingsManga
else -> uiSettingsHome
}
previousStart.alpha = 1f
fun uiDefault(
mode: Int,
current: View,
) {
fun uiDefault(mode: Int, current: View) {
previousStart.alpha = 0.33f
previousStart = current
current.alpha = 1f
@ -440,13 +431,11 @@ class SettingsCommonActivity : AppCompatActivity() {
uiSettingsManga.setOnClickListener {
uiDefault(2, it)
}
}
}
private fun passwordAlertDialog(
isExporting: Boolean,
callback: (CharArray?) -> Unit,
) {
private fun passwordAlertDialog(isExporting: Boolean, callback: (CharArray?) -> Unit) {
val password = CharArray(16).apply { fill('0') }
// Inflate the dialog layout
@ -456,9 +445,7 @@ class SettingsCommonActivity : AppCompatActivity() {
box.setSingleLine()
val dialog =
AlertDialog
.Builder(this, R.style.MyPopup)
.setTitle(getString(R.string.enter_password))
AlertDialog.Builder(this, R.style.MyPopup).setTitle(getString(R.string.enter_password))
.setView(dialogView.root)
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel) { dialog, _ ->
@ -470,10 +457,7 @@ class SettingsCommonActivity : AppCompatActivity() {
fun handleOkAction() {
val editText = dialogView.userAgentTextBox
if (editText.text?.isNotBlank() == true) {
editText.text
?.toString()
?.trim()
?.toCharArray(password)
editText.text?.toString()?.trim()?.toCharArray(password)
dialog.dismiss()
callback(password)
} else {
@ -489,20 +473,18 @@ class SettingsCommonActivity : AppCompatActivity() {
}
}
dialogView.subtitle.visibility = View.VISIBLE
if (!isExporting) {
dialogView.subtitle.text =
if (!isExporting) dialogView.subtitle.text =
getString(R.string.enter_password_to_decrypt_file)
}
dialog.window?.apply {
setDimAmount(0.8f)
attributes.windowAnimations = android.R.style.Animation_Dialog
}
dialog.window?.setDimAmount(0.8f)
dialog.show()
// Override the positive button here
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
handleOkAction()
}
}
}

View file

@ -128,27 +128,26 @@ class SettingsNotificationActivity : AppCompatActivity() {
PrefManager.getVal<Set<String>>(PrefName.AnilistFilteredTypes)
.toMutableSet()
val selected = types.map { filteredTypes.contains(it) }.toBooleanArray()
context.customAlertDialog().apply {
setTitle(R.string.anilist_notification_filters)
multiChoiceItems(
val dialog = AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.anilist_notification_filters)
.setMultiChoiceItems(
types.map { name ->
name.replace("_", " ").lowercase().replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString()
}
}.toTypedArray(),
selected
) { updatedSelected ->
types.forEachIndexed { index, type ->
if (updatedSelected[index]) {
) { _, which, isChecked ->
val type = types[which]
if (isChecked) {
filteredTypes.add(type)
} else {
filteredTypes.remove(type)
}
}
PrefManager.setVal(PrefName.AnilistFilteredTypes, filteredTypes)
}
show()
}
}.create()
dialog.window?.setDimAmount(0.8f)
dialog.show()
}
),
@ -161,24 +160,27 @@ class SettingsNotificationActivity : AppCompatActivity() {
desc = getString(R.string.anilist_notifications_checking_time_desc),
icon = R.drawable.ic_round_notifications_none_24,
onClick = {
context.customAlertDialog().apply {
setTitle(R.string.subscriptions_checking_time)
singleChoiceItems(
aItems.toTypedArray(),
val selected =
PrefManager.getVal<Int>(PrefName.AnilistNotificationInterval)
) { i ->
val dialog = AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.subscriptions_checking_time)
.setSingleChoiceItems(
aItems.toTypedArray(),
selected
) { dialog, i ->
PrefManager.setVal(PrefName.AnilistNotificationInterval, i)
it.settingsTitle.text =
getString(
R.string.anilist_notifications_checking_time,
aItems[i]
)
dialog.dismiss()
TaskScheduler.create(
context, PrefManager.getVal(PrefName.UseAlarmManager)
).scheduleAllTasks(context)
}
show()
}
}.create()
dialog.window?.setDimAmount(0.8f)
dialog.show()
}
),
Settings(
@ -190,24 +192,27 @@ class SettingsNotificationActivity : AppCompatActivity() {
desc = getString(R.string.comment_notification_checking_time_desc),
icon = R.drawable.ic_round_notifications_none_24,
onClick = {
context.customAlertDialog().apply {
setTitle(R.string.subscriptions_checking_time)
singleChoiceItems(
cItems.toTypedArray(),
val selected =
PrefManager.getVal<Int>(PrefName.CommentNotificationInterval)
) { i ->
val dialog = AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.subscriptions_checking_time)
.setSingleChoiceItems(
cItems.toTypedArray(),
selected
) { dialog, i ->
PrefManager.setVal(PrefName.CommentNotificationInterval, i)
it.settingsTitle.text =
getString(
R.string.comment_notification_checking_time,
cItems[i]
)
dialog.dismiss()
TaskScheduler.create(
context, PrefManager.getVal(PrefName.UseAlarmManager)
).scheduleAllTasks(context)
}
show()
}
}.create()
dialog.window?.setDimAmount(0.8f)
dialog.show()
}
),
Settings(
@ -234,10 +239,10 @@ class SettingsNotificationActivity : AppCompatActivity() {
isChecked = PrefManager.getVal(PrefName.UseAlarmManager),
switch = { isChecked, view ->
if (isChecked) {
context.customAlertDialog().apply {
setTitle(R.string.use_alarm_manager)
setMessage(R.string.use_alarm_manager_confirm)
setPosButton(R.string.use) {
val alertDialog = AlertDialog.Builder(context, R.style.MyPopup)
.setTitle(R.string.use_alarm_manager)
.setMessage(R.string.use_alarm_manager_confirm)
.setPositiveButton(R.string.use) { dialog, _ ->
PrefManager.setVal(PrefName.UseAlarmManager, true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (!(getSystemService(Context.ALARM_SERVICE) as AlarmManager).canScheduleExactAlarms()) {
@ -247,13 +252,15 @@ class SettingsNotificationActivity : AppCompatActivity() {
view.settingsButton.isChecked = true
}
}
}
setNegButton(R.string.cancel) {
dialog.dismiss()
}.setNegativeButton(R.string.cancel) { dialog, _ ->
view.settingsButton.isChecked = false
PrefManager.setVal(PrefName.UseAlarmManager, false)
}
show()
}
dialog.dismiss()
}.create()
alertDialog.window?.setDimAmount(0.8f)
alertDialog.show()
} else {
PrefManager.setVal(PrefName.UseAlarmManager, false)
TaskScheduler.create(context, true).cancelAllTasks()

View file

@ -96,8 +96,7 @@ class SettingsThemeActivity : AppCompatActivity(), SimpleDialog.OnDialogResultLi
themeSwitcher.apply {
setText(themeText)
setAdapter(
ArrayAdapter(
context,
ArrayAdapter(context,
R.layout.item_dropdown,
ThemeManager.Companion.Theme.entries.map {
it.theme.substring(

View file

@ -52,8 +52,7 @@ class SubscriptionsBottomDialog : BottomSheetDialogFragment() {
}
groupedSubscriptions.forEach { (parserName, mediaList) ->
adapter.add(
SubscriptionSource(
adapter.add(SubscriptionSource(
parserName,
mediaList.toMutableList(),
adapter,

View file

@ -8,7 +8,7 @@
android:padding="16dp">
<LinearLayout
android:layout_width="326dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
@ -160,8 +160,8 @@
android:orientation="horizontal">
<LinearLayout
android:layout_width="263dp"
android:layout_height="60dp"
android:layout_width="265dp"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
@ -171,23 +171,14 @@
android:fontFamily="@font/poppins_bold"
android:text="@string/download" />
<EditText
<TextView
android:id="@+id/downloadNo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_bold"
android:textColor="?attr/colorSecondary"
android:textSize="12dp"
tools:ignore="TextContrastCheck"
tools:text="Number" />
<!-- <TextView-->
<!-- android:id="@+id/downloadNo"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:fontFamily="@font/poppins_bold"-->
<!-- android:textColor="?attr/colorSecondary"-->
<!-- tools:ignore="TextContrastCheck"-->
<!-- tools:text="number" />-->
tools:text="number" />
</LinearLayout>
<androidx.cardview.widget.CardView
@ -200,7 +191,7 @@
<ImageButton
android:id="@+id/mediaDownloadTop"
android:layout_width="48dp"
android:layout_height="60dp"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackground"
app:srcCompat="@drawable/ic_download_24"
app:tint="?attr/colorOnBackground"
@ -322,9 +313,9 @@
android:text="@string/reset" />
<TextView
android:id="@+id/reset_progress_def"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/reset_progress_def"
android:fontFamily="@font/poppins_bold"
android:text=""
android:textColor="?attr/colorSecondary"

View file

@ -12,7 +12,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:8.9.0'
classpath 'com.android.tools.build:gradle:8.7.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.google.devtools.ksp:symbol-processing-api:$ksp_version"

View file

@ -1,6 +1,6 @@
#Wed Aug 30 19:57:04 IST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View file

@ -1,4 +1,53 @@
# 3.2.1
# 3.1.0
- **New Features:**
- Addons
- Torrent support addon
- Anime downloading addon (mkv files pog)
- Available in app settings
- Anilist reviews in app
- Media subscriptions added to notification tab
- Notification filtering
- Ability to post activitys
- Ability to reply to activities
- Extension tester
- Media subscription Viewer
- Instagram-style stories
- More audio options for some extensions
- Ability to hide items on the home screen
- Ability to set a downloads directory
- 2 functioning widgets
- App lock ( ͡° ͜ʖ ͡°)
- More manga and anime feeds on the home page
- Settings page redesign
- New app crash notifier
- Voice actors
- Additional repo support
- Various UI uplifts
- **Bugfixes:**
- Fix a crash after watching a video
- Scanlator/language not saving after leaving app
- notification red dot not hiding on home pages
- comment/activity scrolling not working on some parts of the screen
- comment notifications falling to the bottom of the list
- Fixed some sources without audio
- Initial app loading time reduced
- activity text more visible
- novel extensions not installing
- Many sources not working
- Subscription notifications not using the correct source
- Notification red dot showing with no new notifications
- Various bug/crash fixes
- General theme tweaks
- Fixed some network-related crashes
- Subscription notifications not working for some people
- Fix for file permissions on older Android versions
- Search list view not working
- Media page opening twice on notification click
- A Special Thanks to all those who contributed :heart:
- **Like what you see?**
- Consider supporting me on [Github](https://github.com/sponsors/rebelonion) or [Buy Me a Coffee](https://www.buymeacoffee.com/rebelonion)!
![alt text](https://media1.tenor.com/m/P7hCyZlzDH4AAAAC/wink-anime.gif)