diff --git a/app/build.gradle b/app/build.gradle index 6c11901a..5caa29de 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,16 +21,18 @@ android { minSdk 23 targetSdk 34 versionCode ((System.currentTimeMillis() / 60000).toInteger()) - versionName "1.0.0-beta03" + versionName "1.0.0-beta03i" signingConfig signingConfigs.debug } buildTypes { debug { applicationIdSuffix ".beta" + manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher_beta"] debuggable true } release { + manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher"] debuggable false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } @@ -76,11 +78,11 @@ dependencies { // FireBase implementation platform('com.google.firebase:firebase-bom:32.2.3') - implementation 'com.google.firebase:firebase-analytics-ktx:21.3.0' - implementation 'com.google.firebase:firebase-crashlytics-ktx:18.4.3' + implementation 'com.google.firebase:firebase-analytics-ktx:21.5.0' + implementation 'com.google.firebase:firebase-crashlytics-ktx:18.6.0' // Exoplayer - ext.exo_version = '1.1.1' + ext.exo_version = '1.2.0' implementation "androidx.media3:media3-exoplayer:$exo_version" implementation "androidx.media3:media3-ui:$exo_version" implementation "androidx.media3:media3-exoplayer-hls:$exo_version" diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml index e74ebc2f..ef58c36a 100644 --- a/app/src/debug/res/values/strings.xml +++ b/app/src/debug/res/values/strings.xml @@ -1,4 +1,4 @@ - Dantotsu + Dantotsu ß \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 991a97c2..84d17a8f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,6 +22,8 @@ + + @@ -46,7 +48,7 @@ = Build.VERSION_CODES.P) { val process = getProcessName() if (packageName != process) WebView.setDataDirectorySuffix(process) @@ -34,28 +37,41 @@ ThemeManager(this).applyTheme() settings.databaseEnabled = true settings.domStorageEnabled = true } - + WebView.setWebContentsDebuggingEnabled(true) webView.webViewClient = object : WebViewClient() { - override fun onPageFinished(view: WebView?, url: String?) { - if (url != null && url.endsWith("/app")) { - webView.stopLoading() - webView.evaluateJavascript(""" - (function() { - const wreq = webpackChunkdiscord_app.push([[Symbol()], {}, w => w]) - webpackChunkdiscord_app.pop() - const token = Object.values(wreq.c).find(m => m.exports?.Z?.getToken).exports.Z.getToken(); - return token; - })() - """.trimIndent()){ - login(it.trim('"')) - } + override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { + // Check if the URL is the one expected after a successful login + if (request?.url.toString() != "https://discord.com/login") { + // Delay the script execution to ensure the page is fully loaded + view?.postDelayed({ + view.evaluateJavascript(""" + (function() { + const wreq = (webpackChunkdiscord_app.push([[''],{},e=>{m=[];for(let c in e.c)m.push(e.c[c])}]),m).find(m=>m?.exports?.default?.getToken!==void 0).exports.default.getToken(); + return wreq; + })() + """.trimIndent()) { result -> + login(result.trim('"')) + } + }, 2000) } + return super.shouldOverrideUrlLoading(view, request) + } + + override fun onPageFinished(view: WebView?, url: String?) { + super.onPageFinished(view, url) } } + webView.loadUrl("https://discord.com/login") } private fun login(token: String) { + if (token.isEmpty() || token == "null"){ + snackString("Failed to retrieve token") + finish() + return + } + snackString("Logged in successfully") finish() saveToken(this, token) startMainActivity(this@Login) diff --git a/app/src/main/java/ani/dantotsu/connections/discord/RPC.kt b/app/src/main/java/ani/dantotsu/connections/discord/RPC.kt index 5c3c720d..90468921 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/RPC.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/RPC.kt @@ -3,10 +3,12 @@ package ani.dantotsu.connections.discord import ani.dantotsu.connections.discord.serializers.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -154,17 +156,15 @@ open class RPC(val token: String, val coroutineContext: CoroutineContext) { webSocket.close(4000, "Interrupt") } - //I hate this, but couldn't find any better way to solve it - suspend fun getUserData(): User { - var user : User? = null + //I kinda hate this + suspend fun getUserData(): User = suspendCancellableCoroutine { continuation -> whenStarted = { - user = it + continuation.resume(it, onCancellation = null) whenStarted = null } - while (user == null) { - delay(100) + continuation.invokeOnCancellation { + whenStarted = null } - return user!! } var onReceiveUserData: ((User) -> Deferred)? = null @@ -185,7 +185,7 @@ open class RPC(val token: String, val coroutineContext: CoroutineContext) { } override fun onMessage(webSocket: WebSocket, text: String) { - println("Message : $text") + println("Discord Message : $text") val map = json.decodeFromString(text) seq = map.s diff --git a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt index 60148260..cdcf6b4c 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt @@ -7,6 +7,7 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageManager +import android.content.pm.ServiceInfo import android.graphics.Bitmap import android.net.Uri import android.os.Build @@ -43,6 +44,7 @@ import ani.dantotsu.snackString import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.gson.GsonBuilder import com.google.gson.InstanceCreator +import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapterImpl import kotlinx.coroutines.CoroutineScope @@ -79,8 +81,12 @@ class MangaDownloaderService : Service() { setOnlyAlertOnce(true) setProgress(0, 0, false) } - startForeground(NOTIFICATION_ID, builder.build()) - ContextCompat.registerReceiver(this, cancelReceiver, IntentFilter(ACTION_CANCEL_DOWNLOAD), ContextCompat.RECEIVER_NOT_EXPORTED) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + startForeground(NOTIFICATION_ID, builder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) + }else{ + startForeground(NOTIFICATION_ID, builder.build()) + } + ContextCompat.registerReceiver(this, cancelReceiver, IntentFilter(ACTION_CANCEL_DOWNLOAD), ContextCompat.RECEIVER_EXPORTED) } override fun onDestroy() { diff --git a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt index 887ae61a..4167a94e 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt @@ -32,6 +32,7 @@ import ani.dantotsu.navBarHeight import ani.dantotsu.px import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.settings.SettingsDialogFragment +import ani.dantotsu.snackString import ani.dantotsu.statusBarHeight import com.google.android.material.card.MaterialCardView import com.google.android.material.imageview.ShapeableImageView @@ -84,12 +85,16 @@ class OfflineMangaFragment: Fragment() { gridView.setOnItemClickListener { parent, view, position, id -> // Get the OfflineMangaModel that was clicked val item = adapter.getItem(position) as OfflineMangaModel - val media = downloadManager.mangaDownloads.filter { it.title == item.title }.first() - startActivity( - Intent(requireContext(), MediaDetailsActivity::class.java) - .putExtra("media", getMedia(media)) - .putExtra("download", true) - ) + val media = downloadManager.mangaDownloads.filter { it.title == item.title }.firstOrNull() + media?.let { + startActivity( + Intent(requireContext(), MediaDetailsActivity::class.java) + .putExtra("media", getMedia(it)) + .putExtra("download", true) + ) + } ?: run { + snackString("no media found") + } } return view diff --git a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt index f850b206..5235e6b5 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt @@ -270,27 +270,7 @@ class MediaDetailsViewModel : ViewModel() { private val mangaChapter = MutableLiveData(null) fun getMangaChapter(): LiveData = mangaChapter suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, series: String, post: Boolean = true): Boolean { - //check if the chapter has been downloaded already - val downloadsManager = Injekt.get() - 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() - directory.listFiles()?.forEach { - if (it.nameWithoutExtension.toIntOrNull() != null) { - images.add(MangaImage(FileUrl(it.absolutePath), false)) - } - } - //sort the images by name - images.sortBy { it.url.url } - chapter.addImages(images) - if (post) mangaChapter.postValue(chapter) - return true - } + return tryWithSuspend(true) { chapter.addImages( mangaReadSources?.get(selected.sourceIndex)?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt index 33dcefe5..a4573ff0 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt @@ -200,7 +200,7 @@ class AnimeWatchAdapter( style = 2 fragment.onIconPressed(style, reversed) } - + binding.animeScanlatorTop.visibility= View.GONE //Episode Handling handleEpisodes() } diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt index 0613eceb..0dc1fda7 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt @@ -321,16 +321,18 @@ class AnimeWatchFragment : Fragment() { dialog.dismiss() // Move the fragment transaction here - val fragment = - 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() + requireActivity().runOnUiThread { + val fragment = + 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() + } } .setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() @@ -340,15 +342,18 @@ class AnimeWatchFragment : Fragment() { .show() } else { // If there's only one setting, proceed with the fragment transaction - val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){ - changeUIVisibility(true) - loadEpisodes(media.selected!!.sourceIndex, true) + requireActivity().runOnUiThread { + val fragment = + 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) diff --git a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt index 5d6df1b7..abf500ce 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt @@ -304,6 +304,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener { 1 -> ResourcesCompat.getFont(this, R.font.poppins_bold) 2 -> ResourcesCompat.getFont(this, R.font.poppins) 3 -> ResourcesCompat.getFont(this, R.font.poppins_thin) + 4 -> ResourcesCompat.getFont(this, R.font.century_gothic_regular) + 5 -> ResourcesCompat.getFont(this, R.font.century_gothic_bold) else -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) } playerView.subtitleView?.setStyle( @@ -321,7 +323,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) LangSet.setLocale(this) -ThemeManager(this).applyTheme() + ThemeManager(this).applyTheme() binding = ActivityExoplayerBinding.inflate(layoutInflater) setContentView(binding.root) @@ -1448,6 +1450,7 @@ ThemeManager(this).applyTheme() override fun onResume() { super.onResume() + LangSet.setLocale(this) orientationListener?.enable() hideSystemBars() if (isInitialized) { diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt index 4480d7a6..b14a81f1 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaChapterAdapter.kt @@ -1,8 +1,12 @@ package ani.dantotsu.media.manga +import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.LinearInterpolator +import androidx.core.content.ContentProviderCompat.requireContext +import androidx.lifecycle.coroutineScope import androidx.recyclerview.widget.RecyclerView import ani.dantotsu.R import ani.dantotsu.databinding.ItemChapterListBinding @@ -10,8 +14,9 @@ import ani.dantotsu.databinding.ItemEpisodeCompactBinding import ani.dantotsu.media.Media import ani.dantotsu.setAnimation import ani.dantotsu.connections.updateProgress -import java.util.regex.Matcher -import java.util.regex.Pattern +import ani.dantotsu.currContext +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch class MangaChapterAdapter( private var type: Int, @@ -90,7 +95,7 @@ class MangaChapterAdapter( } } - fun removeDownload(chapterNumber: String) { + fun purgeDownload(chapterNumber: String) { activeDownloads.remove(chapterNumber) downloadedChapters.remove(chapterNumber) // Find the position of the chapter and notify only that item @@ -112,6 +117,9 @@ class MangaChapterAdapter( inner class ChapterListViewHolder(val binding: ItemChapterListBinding) : RecyclerView.ViewHolder(binding.root) { + private val activeCoroutines = mutableSetOf() + val typedValue1 = TypedValue() + val typedValue2 = TypedValue() fun bind(chapterNumber: String, progress: String?) { if (progress != null) { binding.itemChapterTitle.visibility = View.VISIBLE @@ -122,18 +130,49 @@ class MangaChapterAdapter( } if (activeDownloads.contains(chapterNumber)) { // Show spinner - binding.itemDownload.setImageResource(R.drawable.ic_round_refresh_24) + binding.itemDownload.setImageResource(R.drawable.ic_sync) + startOrContinueRotation(chapterNumber) } else if (downloadedChapters.contains(chapterNumber)) { // Show checkmark - binding.itemDownload.setImageResource(R.drawable.ic_check) + binding.itemDownload.setImageResource(R.drawable.ic_circle_check) + binding.itemDownload.setColorFilter(typedValue2.data) + binding.itemDownload.postDelayed({ + binding.itemDownload.setImageResource(R.drawable.ic_circle_cancel) + binding.itemDownload.setColorFilter(typedValue2.data) + }, 1000) } else { // Show download icon - binding.itemDownload.setImageResource(R.drawable.ic_round_download_24) + binding.itemDownload.setImageResource(R.drawable.ic_circle_add) } } + private fun startOrContinueRotation(chapterNumber: String) { + if (!isRotationCoroutineRunningFor(chapterNumber)) { + val scope = fragment.lifecycle.coroutineScope + scope.launch { + // Add chapter number to active coroutines set + activeCoroutines.add(chapterNumber) + while (activeDownloads.contains(chapterNumber)) { + binding.itemDownload.animate().rotationBy(360f).setDuration(1000).setInterpolator( + LinearInterpolator() + ).start() + delay(1000) + } + // Remove chapter number from active coroutines set + activeCoroutines.remove(chapterNumber) + } + } + } + + private fun isRotationCoroutineRunningFor(chapterNumber: String): Boolean { + return chapterNumber in activeCoroutines + } + init { + val theme = currContext()?.theme + theme?.resolveAttribute(com.google.android.material.R.attr.colorError, typedValue1, true) + theme?.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValue2, true) itemView.setOnClickListener { if (0 <= bindingAdapterPosition && bindingAdapterPosition < arr.size) fragment.onMangaChapterClick(arr[bindingAdapterPosition].number) diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt index 53f24e54..4adc7f0a 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt @@ -2,7 +2,6 @@ package ani.dantotsu.media.manga import android.annotation.SuppressLint import android.app.AlertDialog -import android.app.DownloadManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -16,7 +15,6 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.Toast -import androidx.annotation.RequiresApi import androidx.cardview.widget.CardView import androidx.core.content.ContextCompat import androidx.core.math.MathUtils.clamp @@ -42,7 +40,6 @@ import ani.dantotsu.parsers.HMangaSources import ani.dantotsu.parsers.MangaParser import ani.dantotsu.parsers.MangaSources import ani.dantotsu.settings.UserInterfaceSettings -import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment import ani.dantotsu.subcriptions.Notifications import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP @@ -51,8 +48,6 @@ import ani.dantotsu.subcriptions.SubscriptionHelper import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription import com.google.android.material.appbar.AppBarLayout import com.google.android.material.navigationrail.NavigationRailView -import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource -import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.source.ConfigurableSource import kotlinx.coroutines.CoroutineScope @@ -110,7 +105,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { addAction(ACTION_DOWNLOAD_PROGRESS) } - ContextCompat.registerReceiver(requireContext(), downloadStatusReceiver, intentFilter, ContextCompat.RECEIVER_NOT_EXPORTED) + ContextCompat.registerReceiver(requireContext(), downloadStatusReceiver, intentFilter, ContextCompat.RECEIVER_EXPORTED) binding.animeSourceRecycler.updatePadding(bottom = binding.animeSourceRecycler.paddingBottom + navBarHeight) screenWidth = resources.displayMetrics.widthPixels.dp @@ -405,7 +400,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { // Create a download task val downloadTask = MangaDownloaderService.DownloadTask( - title = media.nameMAL ?: "", + title = media.nameMAL ?: media.nameRomaji, chapter = chapter.title!!, imageData = images, sourceMedia = media, @@ -445,7 +440,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { fun onMangaChapterRemoveDownloadClick(i: String){ - downloadManager.removeDownload(Download(media.nameMAL!!, i, Download.Type.MANGA)) + downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA)) chapterAdapter.deleteDownload(i) } fun onMangaChapterStopDownloadClick(i: String) { @@ -456,8 +451,8 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { requireContext().sendBroadcast(cancelIntent) // Remove the download from the manager and update the UI - downloadManager.removeDownload(Download(media.nameMAL!!, i, Download.Type.MANGA)) - chapterAdapter.stopDownload(i) + downloadManager.removeDownload(Download(media.nameMAL?:media.nameRomaji, i, Download.Type.MANGA)) + chapterAdapter.purgeDownload(i) } private val downloadStatusReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { @@ -475,7 +470,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { ACTION_DOWNLOAD_FAILED -> { val chapterNumber = intent.getStringExtra(EXTRA_CHAPTER_NUMBER) chapterNumber?.let { - chapterAdapter.removeDownload(it) + chapterAdapter.purgeDownload(it) } } diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt index 342203cd..3cf0c0e1 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt @@ -47,7 +47,7 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() { loaded = true binding.selectorAutoText.text = chp.title lifecycleScope.launch(Dispatchers.IO) { - if(model.loadMangaChapterImages(chp, m.selected!!, m.nameMAL!!)) { + if(model.loadMangaChapterImages(chp, m.selected!!, m.nameMAL?:m.nameRomaji)) { val activity = currActivity() activity?.runOnUiThread { tryWith { dismiss() } diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt index dd81e617..a5682716 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt @@ -317,7 +317,7 @@ ThemeManager(this).applyTheme() } } - scope.launch(Dispatchers.IO) { model.loadMangaChapterImages(chapter, media.selected!!, media.nameMAL!!) } + scope.launch(Dispatchers.IO) { model.loadMangaChapterImages(chapter, media.selected!!, media.nameMAL?:media.nameRomaji) } } private val snapHelper = PagerSnapHelper() @@ -706,7 +706,7 @@ ThemeManager(this).applyTheme() model.loadMangaChapterImages( chapters[chaptersArr.getOrNull(currentChapterIndex + 1) ?: return@launch]!!, media.selected!!, - media.nameMAL!!, + media.nameMAL?:media.nameRomaji, false ) loading = false diff --git a/app/src/main/java/ani/dantotsu/others/AppUpdater.kt b/app/src/main/java/ani/dantotsu/others/AppUpdater.kt index 989ec5c5..e6a39fb0 100644 --- a/app/src/main/java/ani/dantotsu/others/AppUpdater.kt +++ b/app/src/main/java/ani/dantotsu/others/AppUpdater.kt @@ -174,7 +174,7 @@ object AppUpdater { } } }, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), - ContextCompat.RECEIVER_NOT_EXPORTED + ContextCompat.RECEIVER_EXPORTED ) return true } diff --git a/app/src/main/java/ani/dantotsu/others/LanguageMapper.kt b/app/src/main/java/ani/dantotsu/others/LanguageMapper.kt new file mode 100644 index 00000000..bd621cb0 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/others/LanguageMapper.kt @@ -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 -> "" + } + } + } +} + diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt index 50e3fed3..3684ee8b 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt @@ -3,6 +3,7 @@ package ani.dantotsu.parsers import android.os.Environment import ani.dantotsu.currContext import ani.dantotsu.download.DownloadsManager +import ani.dantotsu.logger import ani.dantotsu.media.manga.MangaNameAdapter import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga @@ -47,6 +48,7 @@ class OfflineMangaParser: MangaParser() { "Dantotsu/Manga/$chapterLink" ) val images = mutableListOf() + val imageNumberRegex = Regex("""(\d+)\.jpg$""") if (directory.exists()) { directory.listFiles()?.forEach { if (it.isFile) { @@ -54,6 +56,13 @@ class OfflineMangaParser: MangaParser() { images.add(image) } } + images.sortBy { image -> + val matchResult = imageNumberRegex.find(image.url.url) + matchResult?.groups?.get(1)?.value?.toIntOrNull() ?: Int.MAX_VALUE + } + for (image in images) { + logger("imageNumber: ${image.url.url}") + } return images } return emptyList() diff --git a/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt b/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt index 2063825e..3d8a155b 100644 --- a/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/ExtensionsActivity.kt @@ -24,6 +24,7 @@ import ani.dantotsu.themes.ThemeManager import ani.dantotsu.others.LangSet import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator +import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -92,14 +93,14 @@ ThemeManager(this).applyTheme() initActivity(this) + fun bind(extension: AnimeExtension.Available) { + binding.languageselect.setOnClickListener { + val popup = PopupMenu(this, it) - binding.languageselect.setOnClickListener { - val popup = PopupMenu(this, it) - - popup.inflate(R.menu.launguage_selector_menu) - popup.show() + popup.inflate(R.menu.launguage_selector_menu) + popup.show() + } } - binding.settingsContainer.updateLayoutParams { topMargin = statusBarHeight bottomMargin = navBarHeight diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt index 3af4ce55..b668cf2a 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt @@ -13,7 +13,6 @@ import android.widget.ImageView import android.widget.TextView import android.widget.Toast import androidx.core.app.NotificationCompat -import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.DiffUtil @@ -24,6 +23,8 @@ import androidx.viewpager2.widget.ViewPager2 import ani.dantotsu.R import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding import ani.dantotsu.loadData +import ani.dantotsu.others.LanguageMapper +import ani.dantotsu.saveData import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment import com.google.android.material.tabs.TabLayout import com.google.android.material.textfield.TextInputLayout @@ -62,19 +63,26 @@ class InstalledAnimeExtensionsFragment : Fragment() { dialog.dismiss() // Move the fragment transaction here - val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){ - val activity = requireActivity() as ExtensionsActivity - activity.findViewById(R.id.viewPager).visibility = View.VISIBLE - activity.findViewById(R.id.tabLayout).visibility = View.VISIBLE - activity.findViewById(R.id.searchView).visibility = View.VISIBLE - activity.findViewById(R.id.fragmentExtensionsContainer).visibility = - View.GONE + val eActivity = requireActivity() as ExtensionsActivity + eActivity.runOnUiThread { + val fragment = + AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) { + + eActivity.findViewById(R.id.viewPager).visibility = + View.VISIBLE + eActivity.findViewById(R.id.tabLayout).visibility = + View.VISIBLE + eActivity.findViewById(R.id.searchView).visibility = + View.VISIBLE + eActivity.findViewById(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, _ -> dialog.cancel() @@ -83,19 +91,26 @@ class InstalledAnimeExtensionsFragment : Fragment() { .show() } else { // If there's only one setting, proceed with the fragment transaction - val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){ - val activity = requireActivity() as ExtensionsActivity - activity.findViewById(R.id.viewPager).visibility = View.VISIBLE - activity.findViewById(R.id.tabLayout).visibility = View.VISIBLE - activity.findViewById(R.id.searchView).visibility = View.VISIBLE - activity.findViewById(R.id.fragmentExtensionsContainer).visibility = - View.GONE + val eActivity = requireActivity() as ExtensionsActivity + eActivity.runOnUiThread { + val fragment = + AnimeSourcePreferencesFragment().getInstance(selectedSetting.id) { + + eActivity.findViewById(R.id.viewPager).visibility = + View.VISIBLE + eActivity.findViewById(R.id.tabLayout).visibility = + View.VISIBLE + eActivity.findViewById(R.id.searchView).visibility = + View.VISIBLE + eActivity.findViewById(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 @@ -148,7 +163,7 @@ class InstalledAnimeExtensionsFragment : Fragment() { context, Notifications.CHANNEL_DOWNLOADER_PROGRESS ) - .setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check) + .setSmallIcon(R.drawable.ic_circle_check) .setContentTitle("Update complete") .setContentText("The extension has been successfully updated.") .setPriority(NotificationCompat.PRIORITY_LOW) @@ -191,13 +206,11 @@ class InstalledAnimeExtensionsFragment : Fragment() { private class AnimeExtensionsAdapter( private val onSettingsClicked: (AnimeExtension.Installed) -> Unit, private val onUninstallClicked: (AnimeExtension.Installed) -> Unit, - skipIcons: Boolean + val skipIcons: Boolean ) : ListAdapter( DIFF_CALLBACK_INSTALLED ) { - val skipIcons = skipIcons - fun updateData(newExtensions: List) { submitList(newExtensions) // Use submitList instead of manual list handling } @@ -210,14 +223,10 @@ class InstalledAnimeExtensionsFragment : Fragment() { override fun onBindViewHolder(holder: ViewHolder, position: Int) { val extension = getItem(position) // Use getItem() from ListAdapter - val nsfw = if (extension.isNsfw) { - "(18+)" - } else { - "" - } - + val nsfw = if (extension.isNsfw) "(18+)" else "" + val lang= LanguageMapper.mapLanguageCodeToName(extension.lang) holder.extensionNameTextView.text = extension.name - holder.extensionVersionTextView.text = "${extension.versionName} $nsfw" + holder.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw" if (!skipIcons) { holder.extensionIconImageView.setImageDrawable(extension.icon) } diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt index 298feffa..23446c48 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt @@ -14,7 +14,6 @@ import android.widget.ImageView import android.widget.TextView import android.widget.Toast import androidx.core.app.NotificationCompat -import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.DiffUtil @@ -26,6 +25,7 @@ import ani.dantotsu.R import ani.dantotsu.databinding.FragmentMangaExtensionsBinding import ani.dantotsu.loadData import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment +import ani.dantotsu.others.LanguageMapper import com.google.android.material.tabs.TabLayout import com.google.android.material.textfield.TextInputLayout import com.google.firebase.crashlytics.FirebaseCrashlytics @@ -204,13 +204,10 @@ class InstalledMangaExtensionsFragment : Fragment() { override fun onBindViewHolder(holder: ViewHolder, position: Int) { val extension = getItem(position) // Use getItem() from ListAdapter - val nsfw = if (extension.isNsfw) { - "(18+)" - } else { - "" - } + val nsfw = if (extension.isNsfw) "(18+)" else "" + val lang = LanguageMapper.mapLanguageCodeToName(extension.lang) holder.extensionNameTextView.text = extension.name - holder.extensionVersionTextView.text = "${extension.versionName} $nsfw" + holder.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw" if (!skipIcons) { holder.extensionIconImageView.setImageDrawable(extension.icon) } diff --git a/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt index 3d0ec8d8..17fbdb15 100644 --- a/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/PlayerSettingsActivity.kt @@ -378,7 +378,7 @@ ThemeManager(this).applyTheme() dialog.dismiss() }.show() } - val fonts = arrayOf("Poppins Semi Bold", "Poppins Bold", "Poppins", "Poppins Thin") + val fonts = arrayOf("Poppins Semi Bold", "Poppins Bold", "Poppins", "Poppins Thin","Century Gothic","Century Gothic Bold") val fontDialog = AlertDialog.Builder(this, R.style.DialogTheme).setTitle(getString(R.string.subtitle_font)) binding.videoSubFont.setOnClickListener { fontDialog.setSingleChoiceItems(fonts, settings.font) { dialog, count -> diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt index bde659c7..0ef44bc8 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt @@ -35,6 +35,7 @@ import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes import ani.dantotsu.themes.ThemeManager import ani.dantotsu.others.LangSet import com.google.android.material.snackbar.Snackbar +import com.google.android.material.textfield.TextInputEditText import eu.kanade.domain.base.BasePreferences import eu.kanade.tachiyomi.network.NetworkPreferences import io.noties.markwon.Markwon @@ -176,12 +177,28 @@ OS Version: $CODENAME $RELEASE ($SDK_INT) } - binding.userAgent.setText(networkPreferences.defaultUserAgent().get()) - binding.userAgent.setOnEditorActionListener { _, _, _ -> - networkPreferences.defaultUserAgent().set(binding.userAgent.text.toString()) - true + // binding.userAgent.setText(networkPreferences.defaultUserAgent().get()) + binding.userAgent.setOnClickListener{ + val dialogView = layoutInflater.inflate(R.layout.dialog_user_agent, null) + val editText = dialogView.findViewById(R.id.userAgentTextBox) + editText.setText(networkPreferences.defaultUserAgent().get()) + val alertDialog = AlertDialog.Builder(this) + .setView(dialogView) + .setPositiveButton("OK") { dialog, _ -> + networkPreferences.defaultUserAgent().set(editText.text.toString()) + dialog.dismiss() + } + .setNegativeButton("Reset") { dialog, _ -> + networkPreferences.defaultUserAgent().set("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0") // Reset to default or empty + editText.setText("") + dialog.dismiss() + } + .create() + + alertDialog.show() } + val exDns = listOf("None", "Cloudflare", "Google", "AdGuard", "Quad9", "AliDNS", "DNSPod", "360", "Quad101", "Mullvad", "Controld", "Njalla", "Shecan", "Libre") binding.settingsExtensionDns.setText(exDns[networkPreferences.dohProvider().get()], false) binding.settingsExtensionDns.setAdapter(ArrayAdapter(this, R.layout.item_dropdown, exDns)) diff --git a/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt b/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt index b4f93561..b82629f5 100644 --- a/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt +++ b/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt @@ -44,7 +44,7 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() { onCloseAction?.invoke() } - fun populateAnimePreferenceScreen(): PreferenceScreen { + private fun populateAnimePreferenceScreen(): PreferenceScreen { val sourceId = requireArguments().getLong(SOURCE_ID) val source = Injekt.get().get(sourceId)!! check(source is ConfigurableAnimeSource) @@ -57,11 +57,11 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() { pref.isIconSpaceReserved = false if (pref is DialogPreference) { pref.dialogTitle = pref.title - println("pref.dialogTitle: ${pref.dialogTitle}") + //println("pref.dialogTitle: ${pref.dialogTitle}") } - for (entry in sharedPreferences.all.entries) { + /*for (entry in sharedPreferences.all.entries) { Log.d("Preferences", "Key: ${entry.key}, Value: ${entry.value}") - } + }*/ // Apply incognito IME for EditTextPreference if (pref is EditTextPreference) { diff --git a/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt b/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt index 7761ed2e..235d4f15 100644 --- a/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt +++ b/app/src/main/java/ani/dantotsu/settings/paging/AnimePagingSource.kt @@ -1,5 +1,6 @@ package ani.dantotsu.settings.paging +import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.ViewGroup import android.widget.ImageView @@ -15,9 +16,9 @@ import androidx.paging.PagingState import androidx.paging.cachedIn import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView -import ani.dantotsu.settings.SettingsActivity import ani.dantotsu.databinding.ItemExtensionAllBinding import ani.dantotsu.loadData +import ani.dantotsu.others.LanguageMapper import com.bumptech.glide.Glide import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension @@ -78,7 +79,8 @@ class AnimeExtensionPagingSource( val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet() val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions } val query = searchQuery.first() - var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: true + val isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false + val filteredExtensions = if (query.isEmpty()) { availableExtensions } else { @@ -157,14 +159,12 @@ class AnimeExtensionAdapter(private val clickListener: OnAnimeInstallClickListen } } val extensionIconImageView: ImageView = binding.extensionIconImageView + fun bind(extension: AnimeExtension.Available) { - val nsfw = if (extension.isNsfw) { - "(18+)" - } else { - "" - } + val nsfw = if (extension.isNsfw) "(18+)" else "" + val lang= LanguageMapper.mapLanguageCodeToName(extension.lang) binding.extensionNameTextView.text = extension.name - binding.extensionVersionTextView.text = "${extension.versionName} $nsfw" + binding.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw" } } } diff --git a/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt b/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt index e65d5d43..717cb1d2 100644 --- a/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt +++ b/app/src/main/java/ani/dantotsu/settings/paging/MangaPagingSource.kt @@ -1,6 +1,6 @@ package ani.dantotsu.settings.paging -import android.util.Log +import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.ViewGroup import android.widget.ImageView @@ -16,9 +16,9 @@ import androidx.paging.PagingState import androidx.paging.cachedIn import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView -import ani.dantotsu.settings.SettingsActivity import ani.dantotsu.databinding.ItemExtensionAllBinding import ani.dantotsu.loadData +import ani.dantotsu.others.LanguageMapper import com.bumptech.glide.Glide import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager import eu.kanade.tachiyomi.extension.manga.model.MangaExtension @@ -28,7 +28,6 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest -import java.lang.Math.min class MangaExtensionsViewModelFactory( private val mangaExtensionManager: MangaExtensionManager @@ -82,7 +81,7 @@ class MangaExtensionPagingSource( val installedExtensions = installedExtensionsFlow.first().map { it.pkgName }.toSet() val availableExtensions = availableExtensionsFlow.first().filterNot { it.pkgName in installedExtensions } val query = searchQuery.first() - var isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false + val isNsfwEnabled: Boolean = loadData("NFSWExtension") ?: false val filteredExtensions = if (query.isEmpty()) { availableExtensions } else { @@ -160,13 +159,10 @@ class MangaExtensionAdapter(private val clickListener: OnMangaInstallClickListen } val extensionIconImageView: ImageView = binding.extensionIconImageView fun bind(extension: MangaExtension.Available) { - val nsfw = if (extension.isNsfw) { - "(18+)" - } else { - "" - } + val nsfw = if (extension.isNsfw) "(18+)" else "" + val lang= LanguageMapper.mapLanguageCodeToName(extension.lang) binding.extensionNameTextView.text = extension.name - binding.extensionVersionTextView.text = "${extension.versionName} $nsfw" + binding.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw" } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt index a3ae1054..b1fd050b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt @@ -9,6 +9,7 @@ import android.content.IntentFilter import android.content.pm.PackageInstaller import android.os.Build import androidx.core.content.ContextCompat +import ani.dantotsu.snackString import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.util.lang.use import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat @@ -72,12 +73,18 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn service, activeSession!!.second, Intent(INSTALL_ACTION), - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0, + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + PendingIntent.FLAG_MUTABLE + } else 0 ).intentSender session.commit(intentSender) } } catch (e: Exception) { logcat(LogPriority.ERROR, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" } + logcat(LogPriority.ERROR) { "Exception: $e" } + snackString("Failed to install extension ${entry.downloadId} ${entry.uri}") activeSession?.let { (_, sessionId) -> packageInstaller.abandonSession(sessionId) } @@ -101,7 +108,7 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn } init { - ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED) + ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_EXPORTED) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt index c4a6de74..ed1f4e60 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt @@ -28,7 +28,7 @@ internal class AnimeExtensionInstallReceiver(private val listener: Listener) : * Registers this broadcast receiver */ fun register(context: Context) { - ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_NOT_EXPORTED) + ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt index 62ad05c4..fd5353f0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt @@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.extension.anime.util import android.app.Service import android.content.Context import android.content.Intent +import android.content.pm.ServiceInfo import android.net.Uri +import android.os.Build import android.os.IBinder import eu.kanade.domain.base.BasePreferences import ani.dantotsu.R @@ -29,7 +31,11 @@ class AnimeExtensionInstallService : Service() { setContentTitle("Installing Anime Extension...") setProgress(100, 100, true) }.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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt index c303b49c..78686e82 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt @@ -9,6 +9,7 @@ import android.content.IntentFilter import android.content.pm.PackageInstaller import android.os.Build import androidx.core.content.ContextCompat +import ani.dantotsu.snackString import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.util.lang.use import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat @@ -72,12 +73,18 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa service, activeSession!!.second, Intent(INSTALL_ACTION), - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0, + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + PendingIntent.FLAG_MUTABLE + } else 0 ).intentSender session.commit(intentSender) } } catch (e: Exception) { logcat(LogPriority.ERROR) { "Failed to install extension ${entry.downloadId} ${entry.uri}" } + logcat(LogPriority.ERROR) { "Exception: $e" } + snackString("Failed to install extension ${entry.downloadId} ${entry.uri}") activeSession?.let { (_, sessionId) -> packageInstaller.abandonSession(sessionId) } @@ -101,7 +108,7 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa } init { - ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_NOT_EXPORTED) + ContextCompat.registerReceiver(service, packageActionReceiver, IntentFilter(INSTALL_ACTION), ContextCompat.RECEIVER_EXPORTED) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt index 3eb90508..b8688007 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt @@ -28,7 +28,7 @@ internal class MangaExtensionInstallReceiver(private val listener: Listener) : * Registers this broadcast receiver */ fun register(context: Context) { - ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_NOT_EXPORTED) + ContextCompat.registerReceiver(context, this, filter, ContextCompat.RECEIVER_EXPORTED) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt index e4f01c2b..61e5bb74 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt @@ -3,7 +3,11 @@ package eu.kanade.tachiyomi.extension.manga.util import android.app.Service import android.content.Context import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ServiceInfo +import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC import android.net.Uri +import android.os.Build import android.os.IBinder import ani.dantotsu.R import eu.kanade.domain.base.BasePreferences @@ -29,7 +33,11 @@ class MangaExtensionInstallService : Service() { setContentTitle("Installing manga extension...") setProgress(100, 100, true) }.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 { diff --git a/app/src/main/res/drawable/anim_splash_beta.xml b/app/src/main/res/drawable/anim_splash_beta.xml new file mode 100644 index 00000000..3338cb41 --- /dev/null +++ b/app/src/main/res/drawable/anim_splash_beta.xml @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_circle_add.xml b/app/src/main/res/drawable/ic_circle_add.xml new file mode 100644 index 00000000..4f65263e --- /dev/null +++ b/app/src/main/res/drawable/ic_circle_add.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_circle_cancel.xml b/app/src/main/res/drawable/ic_circle_cancel.xml new file mode 100644 index 00000000..72bb239b --- /dev/null +++ b/app/src/main/res/drawable/ic_circle_cancel.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_circle_check.xml b/app/src/main/res/drawable/ic_circle_check.xml new file mode 100644 index 00000000..ea65d8d2 --- /dev/null +++ b/app/src/main/res/drawable/ic_circle_check.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_beta_background.xml b/app/src/main/res/drawable/ic_launcher_beta_background.xml new file mode 100644 index 00000000..657fc674 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_beta_background.xml @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_beta_foreground.xml b/app/src/main/res/drawable/ic_launcher_beta_foreground.xml new file mode 100644 index 00000000..f19b9a98 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_beta_foreground.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_round_delete_24.xml b/app/src/main/res/drawable/ic_round_delete_24.xml index abc47a0b..95e9928f 100644 --- a/app/src/main/res/drawable/ic_round_delete_24.xml +++ b/app/src/main/res/drawable/ic_round_delete_24.xml @@ -1,20 +1,4 @@ - - - - - + diff --git a/app/src/main/res/drawable/ic_sync.xml b/app/src/main/res/drawable/ic_sync.xml new file mode 100644 index 00000000..4ad75e53 --- /dev/null +++ b/app/src/main/res/drawable/ic_sync.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/font/century_gothic_bold.TTF b/app/src/main/res/font/century_gothic_bold.TTF new file mode 100644 index 00000000..93faeb3d Binary files /dev/null and b/app/src/main/res/font/century_gothic_bold.TTF differ diff --git a/app/src/main/res/font/century_gothic_regular.TTF b/app/src/main/res/font/century_gothic_regular.TTF new file mode 100644 index 00000000..a5c1c59f Binary files /dev/null and b/app/src/main/res/font/century_gothic_regular.TTF differ diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 3139a47f..ac29f7b7 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -550,24 +550,46 @@ app:showText="false" app:thumbTint="@color/button_switch_track" /> - + android:layout_height="1dp" + android:layout_marginStart="-16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="-16dp" + android:background="?android:attr/listDivider" /> - +