diff --git a/README.md b/README.md index 6b713a2a..76bece4b 100644 --- a/README.md +++ b/README.md @@ -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! - + ## Terms of Use By downloading, installing, or using this application, you agree to: diff --git a/app/build.gradle b/app/build.gradle index 0604d87e..915b3ba8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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 } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a0e43c2e..7459e050 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - +` diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt index c833f913..4f3509f6 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt @@ -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( 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 eec99b96..20bafb39 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/RPC.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/RPC.kt @@ -50,9 +50,8 @@ 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( - 3, + return json.encodeToString(Presence.Response( + 3, Presence( activities = listOf( Activity( 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 2ea82108..58e7de38 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt @@ -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) } - - saveToDisk("${index.ofLength(3)}.jpg", outputDir, bitmap) farthest++ builder.setProgress(task.imageData.size, farthest, 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 4de053dd..f8a3f725 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt @@ -152,7 +152,6 @@ import ani.dantotsu.toPx import ani.dantotsu.toast import ani.dantotsu.tryWithSuspend import ani.dantotsu.util.Logger -import ani.dantotsu.util.customAlertDialog import com.anggrayudi.storage.file.extension import com.bumptech.glide.Glide import com.google.android.gms.cast.framework.CastButtonFactory @@ -182,10 +181,8 @@ import kotlin.math.roundToInt @UnstableApi @SuppressLint("ClickableViewAccessibility") -class ExoplayerView : - AppCompatActivity(), - Player.Listener, - SessionAvailabilityListener { +class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityListener { + private val resumeWindow = "resumeWindow" private val resumePosition = "resumePosition" private val playerFullscreen = "playerFullscreen" @@ -286,11 +283,10 @@ class ExoplayerView : val displayCutout = window.decorView.rootWindowInsets.displayCutout if (displayCutout != null) { if (displayCutout.boundingRects.size > 0) { - notchHeight = - min( - displayCutout.boundingRects[0].width(), - displayCutout.boundingRects[0].height(), - ) + notchHeight = min( + displayCutout.boundingRects[0].width(), + displayCutout.boundingRects[0].height() + ) checkNotch() } } @@ -301,8 +297,7 @@ class ExoplayerView : private fun checkNotch() { if (notchHeight != 0) { val orientation = resources.configuration.orientation - playerView - .findViewById(R.id.exo_controller_margin) + playerView.findViewById(R.id.exo_controller_margin) .updateLayoutParams { if (orientation == Configuration.ORIENTATION_LANDSCAPE) { marginStart = notchHeight @@ -332,30 +327,28 @@ class ExoplayerView : val secondaryColor = PrefManager.getVal(PrefName.SecondaryColor) - val outline = - when (PrefManager.getVal(PrefName.Outline)) { - 0 -> EDGE_TYPE_OUTLINE // Normal - 1 -> EDGE_TYPE_DEPRESSED // Shine - 2 -> EDGE_TYPE_DROP_SHADOW // Drop shadow - 3 -> EDGE_TYPE_NONE // No outline - else -> EDGE_TYPE_OUTLINE // Normal - } + val outline = when (PrefManager.getVal(PrefName.Outline)) { + 0 -> EDGE_TYPE_OUTLINE // Normal + 1 -> EDGE_TYPE_DEPRESSED // Shine + 2 -> EDGE_TYPE_DROP_SHADOW // Drop shadow + 3 -> EDGE_TYPE_NONE // No outline + else -> EDGE_TYPE_OUTLINE // Normal + } val subBackground = PrefManager.getVal(PrefName.SubBackground) val subWindow = PrefManager.getVal(PrefName.SubWindow) - val font = - when (PrefManager.getVal(PrefName.Font)) { - 0 -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) - 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.levenim_mt_bold) - 6 -> ResourcesCompat.getFont(this, R.font.blocky) - else -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) - } + val font = when (PrefManager.getVal(PrefName.Font)) { + 0 -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) + 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.levenim_mt_bold) + 6 -> ResourcesCompat.getFont(this, R.font.blocky) + else -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) + } val fontSize = PrefManager.getVal(PrefName.FontSize).toFloat() playerView.subtitleView?.let { subtitles -> @@ -369,8 +362,8 @@ class ExoplayerView : subWindow, outline, secondaryColor, - font, - ), + font + ) ) subtitles.alpha = @@ -394,17 +387,16 @@ class ExoplayerView : val fontSize = PrefManager.getVal(PrefName.FontSize).toFloat() - val font = - when (PrefManager.getVal(PrefName.Font)) { - 0 -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) - 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.levenim_mt_bold) - 6 -> ResourcesCompat.getFont(this, R.font.blocky) - else -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) - } + val font = when (PrefManager.getVal(PrefName.Font)) { + 0 -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) + 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.levenim_mt_bold) + 6 -> ResourcesCompat.getFont(this, R.font.blocky) + else -> ResourcesCompat.getFont(this, R.font.poppins_semi_bold) + } textView.setBackgroundColor(subBackground) textView.setTextColor(primaryColor) @@ -439,9 +431,8 @@ class ExoplayerView : binding = ActivityExoplayerBinding.inflate(layoutInflater) setContentView(binding.root) - // Initialize - isCastApiAvailable = GoogleApiAvailability - .getInstance() + //Initialize + isCastApiAvailable = GoogleApiAvailability.getInstance() .isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS try { castContext = @@ -540,34 +531,27 @@ class ExoplayerView : isPlayerPlaying = savedInstanceState.getBoolean(playerOnPlay) } - // BackButton + //BackButton playerView.findViewById(R.id.exo_back).setOnClickListener { onBackPressedDispatcher.onBackPressed() } - // TimeStamps + //TimeStamps model.timeStamps.observe(this) { it -> isTimeStampsLoaded = true - exoSkipOpEd.visibility = - if (it != null) { - val adGroups = - it - .flatMap { - listOf( - it.interval.startTime.toLong() * 1000, - it.interval.endTime.toLong() * 1000, - ) - }.toLongArray() - val playedAdGroups = - it - .flatMap { - listOf(false, false) - }.toBooleanArray() - playerView.setExtraAdGroupMarkers(adGroups, playedAdGroups) - View.VISIBLE - } else { - View.GONE - } + exoSkipOpEd.visibility = if (it != null) { + val adGroups = it.flatMap { + listOf( + it.interval.startTime.toLong() * 1000, + it.interval.endTime.toLong() * 1000 + ) + }.toLongArray() + val playedAdGroups = it.flatMap { + listOf(false, false) + }.toBooleanArray() + playerView.setExtraAdGroupMarkers(adGroups, playedAdGroups) + View.VISIBLE + } else View.GONE } exoSkipOpEd.alpha = if (PrefManager.getVal(PrefName.AutoSkipOPED)) 1f else 0.3f @@ -582,7 +566,7 @@ class ExoplayerView : exoSkipOpEd.alpha = if (PrefManager.getVal(PrefName.AutoSkipOPED)) 1f else 0.3f } - // Play Pause + //Play Pause exoPlay.setOnClickListener { if (isInitialized) { isPlayerPlaying = exoPlayer.isPlaying @@ -606,21 +590,19 @@ class ExoplayerView : // Picture-in-picture if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { pipEnabled = - packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) && - PrefManager.getVal( - PrefName.Pip, - ) + packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) && PrefManager.getVal( + PrefName.Pip + ) if (pipEnabled) { exoPip.visibility = View.VISIBLE exoPip.setOnClickListener { enterPipMode() } - } else { - exoPip.visibility = View.GONE - } + } else exoPip.visibility = View.GONE } - // Lock Button + + //Lock Button var locked = false val container = playerView.findViewById(R.id.exo_controller_cont) val screen = playerView.findViewById(R.id.exo_black_screen) @@ -642,14 +624,13 @@ class ExoplayerView : timeline.setForceDisabled(false) } - // Skip Time Button + //Skip Time Button var skipTime = PrefManager.getVal(PrefName.SkipTime) if (skipTime > 0) { exoSkip.findViewById(R.id.exo_skip_time).text = skipTime.toString() exoSkip.setOnClickListener { - if (isInitialized) { + if (isInitialized) exoPlayer.seekTo(exoPlayer.currentPosition + skipTime * 1000) - } } exoSkip.setOnLongClickListener { val dialog = Dialog(this, R.style.MyPopup) @@ -658,7 +639,7 @@ class ExoplayerView : dialog.setCanceledOnTouchOutside(true) dialog.window?.setLayout( ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT ) if (skipTime <= 120) { dialog.findViewById(R.id.seekbar).value = skipTime.toFloat() @@ -667,24 +648,20 @@ class ExoplayerView : } dialog.findViewById(R.id.seekbar).addOnChangeListener { _, value, _ -> skipTime = value.toInt() - // saveData(player, settings) + //saveData(player, settings) PrefManager.setVal(PrefName.SkipTime, skipTime) playerView.findViewById(R.id.exo_skip_time).text = skipTime.toString() dialog.findViewById(R.id.seekbar_value).text = skipTime.toString() } - dialog - .findViewById(R.id.seekbar) - .addOnSliderTouchListener( - object : Slider.OnSliderTouchListener { - override fun onStartTrackingTouch(slider: Slider) {} - - override fun onStopTrackingTouch(slider: Slider) { - dialog.dismiss() - } - }, - ) + dialog.findViewById(R.id.seekbar) + .addOnSliderTouchListener(object : Slider.OnSliderTouchListener { + override fun onStartTrackingTouch(slider: Slider) {} + override fun onStopTrackingTouch(slider: Slider) { + dialog.dismiss() + } + }) dialog.findViewById(R.id.seekbar_title).text = getString(R.string.skip_time) dialog.findViewById(R.id.seekbar_value).text = @@ -699,136 +676,99 @@ class ExoplayerView : } val gestureSpeed = (300 * PrefManager.getVal(PrefName.AnimationSpeed)).toLong() - // Player UI Visibility Handler - val brightnessRunnable = - Runnable { - if (exoBrightnessCont.alpha == 1f) { - lifecycleScope.launch { - ObjectAnimator - .ofFloat(exoBrightnessCont, "alpha", 1f, 0f) - .setDuration(gestureSpeed) - .start() - delay(gestureSpeed) - exoBrightnessCont.visibility = View.GONE - checkNotch() - } + //Player UI Visibility Handler + val brightnessRunnable = Runnable { + if (exoBrightnessCont.alpha == 1f) + lifecycleScope.launch { + ObjectAnimator.ofFloat(exoBrightnessCont, "alpha", 1f, 0f) + .setDuration(gestureSpeed).start() + delay(gestureSpeed) + exoBrightnessCont.visibility = View.GONE + checkNotch() } + } + val volumeRunnable = Runnable { + if (exoVolumeCont.alpha == 1f) + lifecycleScope.launch { + ObjectAnimator.ofFloat(exoVolumeCont, "alpha", 1f, 0f).setDuration(gestureSpeed) + .start() + delay(gestureSpeed) + exoVolumeCont.visibility = View.GONE + checkNotch() + } + } + playerView.setControllerVisibilityListener(PlayerView.ControllerVisibilityListener { visibility -> + if (visibility == View.GONE) { + hideSystemBars() + brightnessRunnable.run() + volumeRunnable.run() } - val volumeRunnable = - Runnable { - if (exoVolumeCont.alpha == 1f) { - lifecycleScope.launch { - ObjectAnimator - .ofFloat(exoVolumeCont, "alpha", 1f, 0f) - .setDuration(gestureSpeed) - .start() - delay(gestureSpeed) - exoVolumeCont.visibility = View.GONE - checkNotch() - } - } - } - playerView.setControllerVisibilityListener( - PlayerView.ControllerVisibilityListener { visibility -> - if (visibility == View.GONE) { - hideSystemBars() - brightnessRunnable.run() - volumeRunnable.run() - } - }, - ) + }) val overshoot = AnimationUtils.loadInterpolator(this, R.anim.over_shoot) val controllerDuration = (300 * PrefManager.getVal(PrefName.AnimationSpeed)).toLong() - fun handleController() { if (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) !isInPictureInPictureMode else true) { if (playerView.isControllerFullyVisible) { - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_controller), - "alpha", - 1f, - 0f, - ).setDuration(controllerDuration) - .start() - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_bottom_cont), - "translationY", - 0f, - 128f, - ).apply { - interpolator = overshoot - duration = controllerDuration - start() - } - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_timeline_cont), - "translationY", - 0f, - 128f, - ).apply { - interpolator = overshoot - duration = controllerDuration - start() - } - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_top_cont), - "translationY", - 0f, - -128f, - ).apply { - interpolator = overshoot - duration = controllerDuration - start() - } + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_controller), + "alpha", + 1f, + 0f + ) + .setDuration(controllerDuration).start() + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_bottom_cont), + "translationY", + 0f, + 128f + ) + .apply { interpolator = overshoot;duration = controllerDuration;start() } + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_timeline_cont), + "translationY", + 0f, + 128f + ) + .apply { interpolator = overshoot;duration = controllerDuration;start() } + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_top_cont), + "translationY", + 0f, + -128f + ) + .apply { interpolator = overshoot;duration = controllerDuration;start() } playerView.postDelayed({ playerView.hideController() }, controllerDuration) } else { checkNotch() playerView.showController() - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_controller), - "alpha", - 0f, - 1f, - ).setDuration(controllerDuration) - .start() - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_bottom_cont), - "translationY", - 128f, - 0f, - ).apply { - interpolator = overshoot - duration = controllerDuration - start() - } - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_timeline_cont), - "translationY", - 128f, - 0f, - ).apply { - interpolator = overshoot - duration = controllerDuration - start() - } - ObjectAnimator - .ofFloat( - playerView.findViewById(R.id.exo_top_cont), - "translationY", - -128f, - 0f, - ).apply { - interpolator = overshoot - duration = controllerDuration - start() - } + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_controller), + "alpha", + 0f, + 1f + ) + .setDuration(controllerDuration).start() + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_bottom_cont), + "translationY", + 128f, + 0f + ) + .apply { interpolator = overshoot;duration = controllerDuration;start() } + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_timeline_cont), + "translationY", + 128f, + 0f + ) + .apply { interpolator = overshoot;duration = controllerDuration;start() } + ObjectAnimator.ofFloat( + playerView.findViewById(R.id.exo_top_cont), + "translationY", + -128f, + 0f + ) + .apply { interpolator = overshoot;duration = controllerDuration;start() } } } } @@ -842,29 +782,26 @@ class ExoplayerView : val fastForwardCard = playerView.findViewById(R.id.exo_fast_forward) val fastRewindCard = playerView.findViewById(R.id.exo_fast_rewind) - // Seeking + + //Seeking val seekTimerF = ResettableTimer() val seekTimerR = ResettableTimer() var seekTimesF = 0 var seekTimesR = 0 - fun seek( - forward: Boolean, - event: MotionEvent? = null, - ) { + fun seek(forward: Boolean, event: MotionEvent? = null) { val seekTime = PrefManager.getVal(PrefName.SeekTime) - val (card, text) = - if (forward) { - val text = "+${seekTime * ++seekTimesF}" - forwardText.text = text - handler.post { exoPlayer.seekTo(exoPlayer.currentPosition + seekTime * 1000) } - fastForwardCard to forwardText - } else { - val text = "-${seekTime * ++seekTimesR}" - rewindText.text = text - handler.post { exoPlayer.seekTo(exoPlayer.currentPosition - seekTime * 1000) } - fastRewindCard to rewindText - } + val (card, text) = if (forward) { + val text = "+${seekTime * ++seekTimesF}" + forwardText.text = text + handler.post { exoPlayer.seekTo(exoPlayer.currentPosition + seekTime * 1000) } + fastForwardCard to forwardText + } else { + val text = "-${seekTime * ++seekTimesR}" + rewindText.text = text + handler.post { exoPlayer.seekTo(exoPlayer.currentPosition - seekTime * 1000) } + fastRewindCard to rewindText + } //region Double Tap Animation val showCardAnim = ObjectAnimator.ofFloat(card, "alpha", 0f, 1f).setDuration(300) @@ -899,27 +836,21 @@ class ExoplayerView : isSeeking = true if (forward) { - seekTimerR.reset( - object : TimerTask() { - override fun run() { - isSeeking = false - stopAnim() - seekTimesF = 0 - } - }, - 850, - ) + seekTimerR.reset(object : TimerTask() { + override fun run() { + isSeeking = false + stopAnim() + seekTimesF = 0 + } + }, 850) } else { - seekTimerF.reset( - object : TimerTask() { - override fun run() { - isSeeking = false - stopAnim() - seekTimesR = 0 - } - }, - 850, - ) + seekTimerF.reset(object : TimerTask() { + override fun run() { + isSeeking = false + stopAnim() + seekTimesR = 0 + } + }, 850) } } @@ -943,30 +874,27 @@ class ExoplayerView : keyMap[KEYCODE_DPAD_RIGHT] = { seek(true) } keyMap[KEYCODE_DPAD_LEFT] = { seek(false) } - // Screen Gestures + //Screen Gestures if (PrefManager.getVal(PrefName.Gestures) || PrefManager.getVal(PrefName.DoubleTap)) { - fun doubleTap( - forward: Boolean, - event: MotionEvent, - ) { + + fun doubleTap(forward: Boolean, event: MotionEvent) { if (!locked && isInitialized && PrefManager.getVal(PrefName.DoubleTap)) { seek(forward, event) } } - // Brightness + //Brightness var brightnessTimer = Timer() exoBrightnessCont.visibility = View.GONE fun brightnessHide() { brightnessTimer.cancel() brightnessTimer.purge() - val timerTask: TimerTask = - object : TimerTask() { - override fun run() { - handler.post(brightnessRunnable) - } + val timerTask: TimerTask = object : TimerTask() { + override fun run() { + handler.post(brightnessRunnable) } + } brightnessTimer = Timer() brightnessTimer.schedule(timerTask, 3000) } @@ -980,22 +908,20 @@ class ExoplayerView : brightnessHide() } - // Volume + //Volume var volumeTimer = Timer() exoVolumeCont.visibility = View.GONE val volumeMax = audioManager.getStreamMaxVolume(STREAM_MUSIC) exoVolume.value = audioManager.getStreamVolume(STREAM_MUSIC).toFloat() / volumeMax * 10 - fun volumeHide() { volumeTimer.cancel() volumeTimer.purge() - val timerTask: TimerTask = - object : TimerTask() { - override fun run() { - handler.post(volumeRunnable) - } + val timerTask: TimerTask = object : TimerTask() { + override fun run() { + handler.post(volumeRunnable) } + } volumeTimer = Timer() volumeTimer.schedule(timerTask, 3000) } @@ -1005,7 +931,6 @@ class ExoplayerView : volumeHide() } val fastForward = playerView.findViewById(R.id.exo_fast_forward_text) - fun fastForward() { isFastForwarding = true exoPlayer.setPlaybackSpeed(exoPlayer.playbackParameters.speed * 2) @@ -1022,33 +947,29 @@ class ExoplayerView : } } - // FastRewind (Left Panel) - val fastRewindDetector = - GestureDetector( - this, - object : GesturesListener() { - override fun onLongClick(event: MotionEvent) { - if (PrefManager.getVal(PrefName.FastForward)) fastForward() - } + //FastRewind (Left Panel) + val fastRewindDetector = GestureDetector(this, object : GesturesListener() { + override fun onLongClick(event: MotionEvent) { + if (PrefManager.getVal(PrefName.FastForward)) fastForward() + } - override fun onDoubleClick(event: MotionEvent) { - doubleTap(false, event) - } + override fun onDoubleClick(event: MotionEvent) { + doubleTap(false, event) + } - override fun onScrollYClick(y: Float) { - if (!locked && PrefManager.getVal(PrefName.Gestures)) { - exoBrightness.value = clamp(exoBrightness.value + y / 100, 0f, 10f) - if (exoBrightnessCont.visibility != View.VISIBLE) { - exoBrightnessCont.visibility = View.VISIBLE - } - exoBrightnessCont.alpha = 1f - } + override fun onScrollYClick(y: Float) { + if (!locked && PrefManager.getVal(PrefName.Gestures)) { + exoBrightness.value = clamp(exoBrightness.value + y / 100, 0f, 10f) + if (exoBrightnessCont.visibility != View.VISIBLE) { + exoBrightnessCont.visibility = View.VISIBLE } + exoBrightnessCont.alpha = 1f + } + } - override fun onSingleClick(event: MotionEvent) = - if (isSeeking) doubleTap(false, event) else handleController() - }, - ) + override fun onSingleClick(event: MotionEvent) = + if (isSeeking) doubleTap(false, event) else handleController() + }) val rewindArea = playerView.findViewById(R.id.exo_rewind_area) rewindArea.isClickable = true rewindArea.setOnTouchListener { v, event -> @@ -1058,33 +979,29 @@ class ExoplayerView : true } - // FastForward (Right Panel) - val fastForwardDetector = - GestureDetector( - this, - object : GesturesListener() { - override fun onLongClick(event: MotionEvent) { - if (PrefManager.getVal(PrefName.FastForward)) fastForward() - } + //FastForward (Right Panel) + val fastForwardDetector = GestureDetector(this, object : GesturesListener() { + override fun onLongClick(event: MotionEvent) { + if (PrefManager.getVal(PrefName.FastForward)) fastForward() + } - override fun onDoubleClick(event: MotionEvent) { - doubleTap(true, event) - } + override fun onDoubleClick(event: MotionEvent) { + doubleTap(true, event) + } - override fun onScrollYClick(y: Float) { - if (!locked && PrefManager.getVal(PrefName.Gestures)) { - exoVolume.value = clamp(exoVolume.value + y / 100, 0f, 10f) - if (exoVolumeCont.visibility != View.VISIBLE) { - exoVolumeCont.visibility = View.VISIBLE - } - exoVolumeCont.alpha = 1f - } + override fun onScrollYClick(y: Float) { + if (!locked && PrefManager.getVal(PrefName.Gestures)) { + exoVolume.value = clamp(exoVolume.value + y / 100, 0f, 10f) + if (exoVolumeCont.visibility != View.VISIBLE) { + exoVolumeCont.visibility = View.VISIBLE } + exoVolumeCont.alpha = 1f + } + } - override fun onSingleClick(event: MotionEvent) = - if (isSeeking) doubleTap(true, event) else handleController() - }, - ) + override fun onSingleClick(event: MotionEvent) = + if (isSeeking) doubleTap(true, event) else handleController() + }) val forwardArea = playerView.findViewById(R.id.exo_forward_area) forwardArea.isClickable = true forwardArea.setOnTouchListener { v, event -> @@ -1095,7 +1012,7 @@ class ExoplayerView : } } - // Handle Media + //Handle Media if (!initialized) return startMainActivity(this) model.setMedia(media) title = media.userPreferredName @@ -1109,7 +1026,8 @@ class ExoplayerView : epChanging = !it } - // Anime Title + + //Anime Title animeTitle.text = media.userPreferredName episodeArr = episodes.keys.toList() @@ -1119,18 +1037,16 @@ class ExoplayerView : episodes.forEach { val episode = it.value val cleanedTitle = MediaNameAdapter.removeEpisodeNumberCompletely(episode.title ?: "") - episodeTitleArr.add( - "Episode ${episode.number}${if (episode.filler) " [Filler]" else ""}${if (cleanedTitle.isNotBlank() && cleanedTitle != "null") ": $cleanedTitle" else ""}", - ) + episodeTitleArr.add("Episode ${episode.number}${if (episode.filler) " [Filler]" else ""}${if (cleanedTitle.isNotBlank() && cleanedTitle != "null") ": $cleanedTitle" else ""}") } - // Episode Change + //Episode Change fun change(index: Int) { if (isInitialized) { changingServer = false PrefManager.setCustomVal( "${media.id}_${episodeArr[currentEpisodeIndex]}", - exoPlayer.currentPosition, + exoPlayer.currentPosition ) exoPlayer.seekTo(0) val prev = episodeArr[currentEpisodeIndex] @@ -1141,37 +1057,29 @@ class ExoplayerView : model.epChanged.postValue(false) model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "change") model.onEpisodeClick( - media, - media.anime!!.selectedEpisode!!, - this.supportFragmentManager, + media, media.anime!!.selectedEpisode!!, this.supportFragmentManager, false, - prev, + prev ) } } - // EpisodeSelector + //EpisodeSelector episodeTitle.adapter = NoPaddingArrayAdapter(this, R.layout.item_dropdown, episodeTitleArr) episodeTitle.setSelection(currentEpisodeIndex) - episodeTitle.onItemSelectedListener = - object : AdapterView.OnItemSelectedListener { - override fun onItemSelected( - p0: AdapterView<*>?, - p1: View?, - position: Int, - p3: Long, - ) { - if (position != currentEpisodeIndex) { - disappeared = false - functionstarted = false - change(position) - } + episodeTitle.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(p0: AdapterView<*>?, p1: View?, position: Int, p3: Long) { + if (position != currentEpisodeIndex) { + disappeared = false + functionstarted = false + change(position) } - - override fun onNothingSelected(parent: AdapterView<*>) {} } - // Next Episode + override fun onNothingSelected(parent: AdapterView<*>) {} + } + + //Next Episode exoNext = playerView.findViewById(R.id.exo_next_ep) exoNext.setOnClickListener { if (isInitialized) { @@ -1183,15 +1091,14 @@ class ExoplayerView : } } } - // Prev Episode + //Prev Episode exoPrev = playerView.findViewById(R.id.exo_prev_ep) exoPrev.setOnClickListener { if (currentEpisodeIndex > 0) { disappeared = false change(currentEpisodeIndex - 1) - } else { + } else snackString(getString(R.string.first_episode)) - } } model.getEpisode().observe(this) { ep -> @@ -1203,48 +1110,45 @@ class ExoplayerView : currentEpisodeIndex = episodeArr.indexOf(ep.number) episodeTitle.setSelection(currentEpisodeIndex) if (isInitialized) releasePlayer() - playbackPosition = - PrefManager.getCustomVal( - "${media.id}_${ep.number}", - 0, - ) + playbackPosition = PrefManager.getCustomVal( + "${media.id}_${ep.number}", + 0 + ) initPlayer() preloading = false updateProgress() } } - // FullScreen + //FullScreen isFullscreen = PrefManager.getCustomVal("${media.id}_fullscreenInt", isFullscreen) - playerView.resizeMode = - when (isFullscreen) { + playerView.resizeMode = when (isFullscreen) { + 0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT + 1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM + 2 -> AspectRatioFrameLayout.RESIZE_MODE_FILL + else -> AspectRatioFrameLayout.RESIZE_MODE_FIT + } + + exoScreen.setOnClickListener { + if (isFullscreen < 2) isFullscreen += 1 else isFullscreen = 0 + playerView.resizeMode = when (isFullscreen) { 0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT 1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM 2 -> AspectRatioFrameLayout.RESIZE_MODE_FILL else -> AspectRatioFrameLayout.RESIZE_MODE_FIT } - - exoScreen.setOnClickListener { - if (isFullscreen < 2) isFullscreen += 1 else isFullscreen = 0 - playerView.resizeMode = - when (isFullscreen) { - 0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT - 1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM - 2 -> AspectRatioFrameLayout.RESIZE_MODE_FILL - else -> AspectRatioFrameLayout.RESIZE_MODE_FIT - } snackString( when (isFullscreen) { 0 -> "Original" 1 -> "Zoom" 2 -> "Stretch" else -> "Original" - }, + } ) PrefManager.setCustomVal("${media.id}_fullscreenInt", isFullscreen) } - // Cast + //Cast if (PrefManager.getVal(PrefName.Cast)) { playerView.findViewById(R.id.exo_cast).apply { visibility = View.VISIBLE @@ -1261,25 +1165,24 @@ class ExoplayerView : } } - // Settings + //Settings exoSettings.setOnClickListener { PrefManager.setCustomVal( "${media.id}_${media.anime!!.selectedEpisode}", - exoPlayer.currentPosition, + exoPlayer.currentPosition ) - val intent = - Intent(this, PlayerSettingsActivity::class.java).apply { - putExtra("subtitle", subtitle) - } + val intent = Intent(this, PlayerSettingsActivity::class.java).apply { + putExtra("subtitle", subtitle) + } exoPlayer.pause() onChangeSettings.launch(intent) } - // Speed + //Speed val speeds = - if (PrefManager.getVal(PrefName.CursedSpeeds)) { + if (PrefManager.getVal(PrefName.CursedSpeeds)) arrayOf(1f, 1.25f, 1.5f, 1.75f, 2f, 2.5f, 3f, 4f, 5f, 10f, 25f, 50f) - } else { + else arrayOf( 0.25f, 0.33f, @@ -1293,39 +1196,38 @@ class ExoplayerView : 1.5f, 1.66f, 1.75f, - 2f, + 2f ) - } val speedsName = speeds.map { "${it}x" }.toTypedArray() - // var curSpeed = loadData("${media.id}_speed", this) ?: settings.defaultSpeed - var curSpeed = - PrefManager.getCustomVal( - "${media.id}_speed", - PrefManager.getVal(PrefName.DefaultSpeed), - ) + //var curSpeed = loadData("${media.id}_speed", this) ?: settings.defaultSpeed + var curSpeed = PrefManager.getCustomVal( + "${media.id}_speed", + PrefManager.getVal(PrefName.DefaultSpeed) + ) playbackParameters = PlaybackParameters(speeds[curSpeed]) var speed: Float + val speedDialog = + AlertDialog.Builder(this, R.style.MyPopup).setTitle(getString(R.string.speed)) exoSpeed.setOnClickListener { - customAlertDialog().apply { - setTitle(R.string.speed) - singleChoiceItems(speedsName, curSpeed) { i -> + val dialog = speedDialog.setSingleChoiceItems(speedsName, curSpeed) { dialog, i -> + if (isInitialized) { PrefManager.setCustomVal("${media.id}_speed", i) speed = speeds[i] curSpeed = i playbackParameters = PlaybackParameters(speed) exoPlayer.playbackParameters = playbackParameters + dialog.dismiss() hideSystemBars() } - setOnCancelListener { hideSystemBars() } - show() - } + }.show() + dialog.window?.setDimAmount(0.8f) } + speedDialog.setOnCancelListener { hideSystemBars() } if (PrefManager.getVal(PrefName.AutoPlay)) { var touchTimer = Timer() - fun touched() { interacted = true touchTimer.apply { @@ -1333,14 +1235,11 @@ class ExoplayerView : purge() } touchTimer = Timer() - touchTimer.schedule( - object : TimerTask() { - override fun run() { - interacted = false - } - }, - 1000 * 60 * 60, - ) + touchTimer.schedule(object : TimerTask() { + override fun run() { + interacted = false + } + }, 1000 * 60 * 60) } playerView.findViewById(R.id.exo_touch_view).setOnTouchListener { _, _ -> touched() @@ -1349,73 +1248,62 @@ class ExoplayerView : } isFullscreen = PrefManager.getVal(PrefName.Resize) - playerView.resizeMode = - when (isFullscreen) { - 0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT - 1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM - 2 -> AspectRatioFrameLayout.RESIZE_MODE_FILL - else -> AspectRatioFrameLayout.RESIZE_MODE_FIT - } + playerView.resizeMode = when (isFullscreen) { + 0 -> AspectRatioFrameLayout.RESIZE_MODE_FIT + 1 -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM + 2 -> AspectRatioFrameLayout.RESIZE_MODE_FILL + else -> AspectRatioFrameLayout.RESIZE_MODE_FIT + } preloading = false val incognito: Boolean = PrefManager.getVal(PrefName.Incognito) val showProgressDialog = - if (PrefManager.getVal(PrefName.AskIndividualPlayer)) { - PrefManager.getCustomVal( - "${media.id}_ProgressDialog", - true, - ) - } else { - false - } - if (!incognito && - showProgressDialog && - Anilist.userid != null && - if (media.isAdult) { - PrefManager.getVal( - PrefName.UpdateForHPlayer, - ) - } else { + if (PrefManager.getVal(PrefName.AskIndividualPlayer)) PrefManager.getCustomVal( + "${media.id}_ProgressDialog", true - } + ) else false + if (!incognito && showProgressDialog && Anilist.userid != null && if (media.isAdult) PrefManager.getVal( + PrefName.UpdateForHPlayer + ) else true ) { - customAlertDialog().apply { - setTitle(getString(R.string.auto_update, media.userPreferredName)) - setCancelable(false) - setPosButton(R.string.yes) { - PrefManager.setCustomVal( - "${media.id}_ProgressDialog", - false, - ) - PrefManager.setCustomVal( - "${media.id}_save_progress", - true, - ) - model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") + AlertDialog.Builder(this, R.style.MyPopup) + .setTitle(getString(R.string.auto_update, media.userPreferredName)) + .apply { + setOnCancelListener { hideSystemBars() } + setCancelable(false) + setPositiveButton(getString(R.string.yes)) { dialog, _ -> + PrefManager.setCustomVal( + "${media.id}_ProgressDialog", + false + ) + PrefManager.setCustomVal( + "${media.id}_save_progress", + true + ) + dialog.dismiss() + model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") + } + setNegativeButton(getString(R.string.no)) { dialog, _ -> + PrefManager.setCustomVal( + "${media.id}_ProgressDialog", + false + ) + PrefManager.setCustomVal( + "${media.id}_save_progress", + false + ) + toast(getString(R.string.reset_auto_update)) + dialog.dismiss() + model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") + } + show() } - setNegButton(R.string.no) { - PrefManager.setCustomVal( - "${media.id}_ProgressDialog", - false, - ) - PrefManager.setCustomVal( - "${media.id}_save_progress", - false, - ) - toast(getString(R.string.reset_auto_update)) - model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") - } - setOnCancelListener { hideSystemBars() } - show() - } - } else { - model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") - } + } else model.setEpisode(episodes[media.anime!!.selectedEpisode!!]!!, "invoke") - // Start the recursive Fun - if (PrefManager.getVal(PrefName.TimeStampsEnabled)) { + //Start the recursive Fun + if (PrefManager.getVal(PrefName.TimeStampsEnabled)) updateTimeStamp() - } + } private fun discordRPC() { @@ -1427,68 +1315,60 @@ class ExoplayerView : if ((isOnline(context) && !offline) && Discord.token != null && !incognito && rpcenabled) { lifecycleScope.launch { val discordMode = PrefManager.getCustomVal("discord_mode", "dantotsu") - val buttons = - when (discordMode) { - "nothing" -> - mutableListOf( - RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), - ) + val buttons = when (discordMode) { + "nothing" -> mutableListOf( + RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), + ) - "dantotsu" -> - mutableListOf( - RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), - RPC.Link("Watch on Dantotsu", getString(R.string.dantotsu)), - ) + "dantotsu" -> mutableListOf( + RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), + RPC.Link("Watch on Dantotsu", getString(R.string.dantotsu)) + ) - "anilist" -> { - val userId = PrefManager.getVal(PrefName.AnilistUserId) - val anilistLink = "https://anilist.co/user/$userId/" - mutableListOf( - RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), - RPC.Link("View My AniList", anilistLink), - ) - } - - else -> mutableListOf() + "anilist" -> { + val userId = PrefManager.getVal(PrefName.AnilistUserId) + val anilistLink = "https://anilist.co/user/$userId/" + mutableListOf( + RPC.Link(getString(R.string.view_anime), media.shareLink ?: ""), + RPC.Link("View My AniList", anilistLink) + ) } + + else -> mutableListOf() + } val startTimestamp = Calendar.getInstance() val durationInSeconds = if (exoPlayer.duration != C.TIME_UNSET) (exoPlayer.duration / 1000).toInt() else 1440 - val endTimestamp = - Calendar.getInstance().apply { - timeInMillis = startTimestamp.timeInMillis - add(Calendar.SECOND, durationInSeconds) - } - val presence = - RPC.createPresence( - RPC.Companion.RPCData( - applicationId = Discord.application_Id, - type = RPC.Type.WATCHING, - activityName = media.userPreferredName, - details = - ep.title?.takeIf { it.isNotEmpty() } ?: getString( - R.string.episode_num, - ep.number, - ), - startTimestamp = startTimestamp.timeInMillis, - stopTimestamp = endTimestamp.timeInMillis, - state = "Episode : ${ep.number}/${media.anime?.totalEpisodes ?: "??"}", - largeImage = - media.cover?.let { - RPC.Link( - media.userPreferredName, - it, - ) - }, - smallImage = RPC.Link("Dantotsu", Discord.small_Image), - buttons = buttons, + val endTimestamp = Calendar.getInstance().apply { + timeInMillis = startTimestamp.timeInMillis + add(Calendar.SECOND, durationInSeconds) + } + val presence = RPC.createPresence( + RPC.Companion.RPCData( + applicationId = Discord.application_Id, + type = RPC.Type.WATCHING, + activityName = media.userPreferredName, + details = ep.title?.takeIf { it.isNotEmpty() } ?: getString( + R.string.episode_num, + ep.number ), + startTimestamp = startTimestamp.timeInMillis, + stopTimestamp = endTimestamp.timeInMillis, + state = "Episode : ${ep.number}/${media.anime?.totalEpisodes ?: "??"}", + largeImage = media.cover?.let { + RPC.Link( + media.userPreferredName, + it + ) + }, + smallImage = RPC.Link("Dantotsu", Discord.small_Image), + buttons = buttons ) - val intent = - Intent(context, DiscordService::class.java).apply { - putExtra("presence", presence) - } + ) + val intent = Intent(context, DiscordService::class.java).apply { + putExtra("presence", presence) + } DiscordServiceRunningSingleton.running = true startService(intent) } @@ -1500,18 +1380,15 @@ class ExoplayerView : PrefManager.setCustomVal( "${media.id}_current_ep", - media.anime!!.selectedEpisode!!, + media.anime!!.selectedEpisode!! ) @Suppress("UNCHECKED_CAST") - val list = - ( - PrefManager.getNullableCustomVal( - "continueAnimeList", - listOf(), - List::class.java, - ) as List - ).toMutableList() + val list = (PrefManager.getNullableCustomVal( + "continueAnimeList", + listOf(), + List::class.java + ) as List).toMutableList() if (list.contains(media.id)) list.remove(media.id) list.add(media.id) PrefManager.setCustomVal("continueAnimeList", list) @@ -1523,71 +1400,62 @@ class ExoplayerView : val ext = episode.extractors?.find { it.server.name == episode.selectedExtractor } ?: return extractor = ext video = ext.videos.getOrNull(episode.selectedVideo) ?: return - val subLanguages = - arrayOf( - "Albanian", - "Arabic", - "Bosnian", - "Bulgarian", - "Chinese", - "Croatian", - "Czech", - "Danish", - "Dutch", - "English", - "Estonian", - "Finnish", - "French", - "Georgian", - "German", - "Greek", - "Hebrew", - "Hindi", - "Indonesian", - "Irish", - "Italian", - "Japanese", - "Korean", - "Lithuanian", - "Luxembourgish", - "Macedonian", - "Mongolian", - "Norwegian", - "Polish", - "Portuguese", - "Punjabi", - "Romanian", - "Russian", - "Serbian", - "Slovak", - "Slovenian", - "Spanish", - "Turkish", - "Ukrainian", - "Urdu", - "Vietnamese", - ) + val subLanguages = arrayOf( + "Albanian", + "Arabic", + "Bosnian", + "Bulgarian", + "Chinese", + "Croatian", + "Czech", + "Danish", + "Dutch", + "English", + "Estonian", + "Finnish", + "French", + "Georgian", + "German", + "Greek", + "Hebrew", + "Hindi", + "Indonesian", + "Irish", + "Italian", + "Japanese", + "Korean", + "Lithuanian", + "Luxembourgish", + "Macedonian", + "Mongolian", + "Norwegian", + "Polish", + "Portuguese", + "Punjabi", + "Romanian", + "Russian", + "Serbian", + "Slovak", + "Slovenian", + "Spanish", + "Turkish", + "Ukrainian", + "Urdu", + "Vietnamese", + ) val lang = subLanguages[PrefManager.getVal(PrefName.SubLanguage)] subtitle = intent.getSerialized("subtitle") - ?: when ( - val subLang: String? = - PrefManager.getNullableCustomVal( - "subLang_${media.id}", - null, - String::class.java - ) - ) { + ?: when (val subLang: String? = + PrefManager.getNullableCustomVal("subLang_${media.id}", null, String::class.java)) { null -> { when (episode.selectedSubtitle) { null -> null - -1 -> - ext.subtitles.find { - it.language.contains(lang, ignoreCase = true) || - it.language.contains( - getLanguageCode(lang), - ignoreCase = true - ) - } + -1 -> ext.subtitles.find { + it.language.contains( + lang, + ignoreCase = true + ) || it.language.contains(getLanguageCode(lang), ignoreCase = true) + } else -> ext.subtitles.getOrNull(episode.selectedSubtitle!!) } @@ -1597,7 +1465,7 @@ class ExoplayerView : else -> ext.subtitles.find { it.language == subLang } } - // Subtitles + //Subtitles hasExtSubtitles = ext.subtitles.isNotEmpty() if (hasExtSubtitles) { exoSubtitle.isVisible = hasExtSubtitles @@ -1609,43 +1477,43 @@ class ExoplayerView : emptyList().toMutableList() ext.subtitles.forEach { subtitle -> val subtitleUrl = if (!hasExtSubtitles) video!!.file.url else subtitle.file.url - // var localFile: String? = null + //var localFile: String? = null if (subtitle.type == SubtitleType.UNKNOWN) { runBlocking { val type = SubtitleDownloader.loadSubtitleType(subtitleUrl) val fileUri = Uri.parse(subtitleUrl) - sub += - MediaItem.SubtitleConfiguration - .Builder(fileUri) - .setSelectionFlags(C.SELECTION_FLAG_DEFAULT) - .setMimeType( - when (type) { - SubtitleType.VTT -> MimeTypes.TEXT_SSA - SubtitleType.ASS -> MimeTypes.TEXT_SSA - SubtitleType.SRT -> MimeTypes.TEXT_SSA - else -> MimeTypes.TEXT_SSA - }, - ).setId("69") - .setLanguage(subtitle.language) - .build() + sub += MediaItem.SubtitleConfiguration + .Builder(fileUri) + .setSelectionFlags(C.SELECTION_FLAG_DEFAULT) + .setMimeType( + when (type) { + SubtitleType.VTT -> MimeTypes.TEXT_SSA + SubtitleType.ASS -> MimeTypes.TEXT_SSA + SubtitleType.SRT -> MimeTypes.TEXT_SSA + else -> MimeTypes.TEXT_SSA + } + ) + .setId("69") + .setLanguage(subtitle.language) + .build() } println("sub: $sub") } else { val subUri = Uri.parse(subtitleUrl) - sub += - MediaItem.SubtitleConfiguration - .Builder(subUri) - .setSelectionFlags(C.SELECTION_FLAG_FORCED) - .setMimeType( - when (subtitle.type) { - SubtitleType.VTT -> MimeTypes.TEXT_VTT - SubtitleType.ASS -> MimeTypes.TEXT_SSA - SubtitleType.SRT -> MimeTypes.APPLICATION_SUBRIP - else -> MimeTypes.TEXT_UNKNOWN - }, - ).setId("69") - .setLanguage(subtitle.language) - .build() + sub += MediaItem.SubtitleConfiguration + .Builder(subUri) + .setSelectionFlags(C.SELECTION_FLAG_FORCED) + .setMimeType( + when (subtitle.type) { + SubtitleType.VTT -> MimeTypes.TEXT_VTT + SubtitleType.ASS -> MimeTypes.TEXT_SSA + SubtitleType.SRT -> MimeTypes.APPLICATION_SUBRIP + else -> MimeTypes.TEXT_UNKNOWN + } + ) + .setId("69") + .setLanguage(subtitle.language) + .build() } } @@ -1653,140 +1521,98 @@ class ExoplayerView : ext.onVideoPlayed(video) } - val httpClient = - okHttpClient - .newBuilder() - .apply { - ignoreAllSSLErrors() - followRedirects(true) - followSslRedirects(true) - }.build() - val dataSourceFactory = - DataSource.Factory { - val dataSource: HttpDataSource = - OkHttpDataSource.Factory(httpClient).createDataSource() - defaultHeaders.forEach { - dataSource.setRequestProperty(it.key, it.value) - } - video?.file?.headers?.forEach { - dataSource.setRequestProperty(it.key, it.value) - } - dataSource + val httpClient = okHttpClient.newBuilder().apply { + ignoreAllSSLErrors() + followRedirects(true) + followSslRedirects(true) + }.build() + val dataSourceFactory = DataSource.Factory { + val dataSource: HttpDataSource = OkHttpDataSource.Factory(httpClient).createDataSource() + defaultHeaders.forEach { + dataSource.setRequestProperty(it.key, it.value) } + video?.file?.headers?.forEach { + dataSource.setRequestProperty(it.key, it.value) + } + dataSource + } val dafuckDataSourceFactory = DefaultDataSource.Factory(this) - cacheFactory = - CacheDataSource.Factory().apply { - setCache(VideoCache.getInstance(this@ExoplayerView)) - if (ext.server.offline) { - setUpstreamDataSourceFactory(dafuckDataSourceFactory) - } else { - setUpstreamDataSourceFactory(dataSourceFactory) - } - setCacheWriteDataSinkFactory(null) - } - - val mimeType = - when (video?.format) { - VideoType.M3U8 -> MimeTypes.APPLICATION_M3U8 - VideoType.DASH -> MimeTypes.APPLICATION_MPD - else -> MimeTypes.APPLICATION_MP4 - } - - val downloadedMediaItem = + cacheFactory = CacheDataSource.Factory().apply { + setCache(VideoCache.getInstance(this@ExoplayerView)) if (ext.server.offline) { - val titleName = - ext.server.name - .split("/") - .first() - val episodeName = - ext.server.name - .split("/") - .last() - downloadId = PrefManager - .getAnimeDownloadPreferences() - .getString("$titleName - $episodeName", null) - ?: PrefManager - .getAnimeDownloadPreferences() - .getString(ext.server.name, null) - val exoItem = - if (downloadId != null) { - Helper - .downloadManager(this) - .downloadIndex - .getDownload(downloadId!!) - ?.request - ?.toMediaItem() - } else { - null - } - if (exoItem != null) { - exoItem - } else { - val directory = - getSubDirectory(this, MediaType.ANIME, false, titleName, episodeName) - if (directory != null) { - val files = directory.listFiles() - println(files) - val docFile = - directory.listFiles().firstOrNull { - it.name?.endsWith(".mp4") == true || - it.name?.endsWith(".mkv") == true || - it.name?.endsWith( - ".${ - Injekt - .get() - .extension - ?.extension - ?.getFileExtension() - ?.first ?: "ts" - }", - ) == - true - } - if (docFile != null) { - val uri = docFile.uri - val downloadedMimeType = - when (docFile.extension) { - "mp4" -> MimeTypes.APPLICATION_MP4 - "mkv" -> MimeTypes.APPLICATION_MATROSKA - else -> MimeTypes.APPLICATION_MP4 - } - MediaItem - .Builder() - .setUri(uri) - .setMimeType(downloadedMimeType) - .build() - } else { - snackString("File not found") - null - } - } else { - snackString("Directory not found") - null - } - } + setUpstreamDataSourceFactory(dafuckDataSourceFactory) } else { - null + setUpstreamDataSourceFactory(dataSourceFactory) } + setCacheWriteDataSinkFactory(null) + } - mediaItem = - if (downloadedMediaItem == null) { - val builder = MediaItem.Builder().setUri(video!!.file.url).setMimeType(mimeType) - Logger.log("url: ${video!!.file.url}") - Logger.log("mimeType: $mimeType") - builder.setSubtitleConfigurations(sub) - builder.build() + val mimeType = when (video?.format) { + VideoType.M3U8 -> MimeTypes.APPLICATION_M3U8 + VideoType.DASH -> MimeTypes.APPLICATION_MPD + else -> MimeTypes.APPLICATION_MP4 + } + + val downloadedMediaItem = if (ext.server.offline) { + val titleName = ext.server.name.split("/").first() + val episodeName = ext.server.name.split("/").last() + downloadId = PrefManager.getAnimeDownloadPreferences() + .getString("$titleName - $episodeName", null) + ?: PrefManager.getAnimeDownloadPreferences() + .getString(ext.server.name, null) + val exoItem = if (downloadId != null) { + Helper.downloadManager(this) + .downloadIndex.getDownload(downloadId!!)?.request?.toMediaItem() + } else null + if (exoItem != null) { + exoItem } else { - if (sub.isNotEmpty()) { - val addedSubsDownloadedMediaItem = downloadedMediaItem.buildUpon() - val addLanguage = sub[0].buildUpon().setLanguage("en").build() - addedSubsDownloadedMediaItem.setSubtitleConfigurations(listOf(addLanguage)) - episode.selectedSubtitle = 0 - addedSubsDownloadedMediaItem.build() + + val directory = + getSubDirectory(this, MediaType.ANIME, false, titleName, episodeName) + if (directory != null) { + val files = directory.listFiles() + println(files) + val docFile = directory.listFiles().firstOrNull { + it.name?.endsWith(".mp4") == true || it.name?.endsWith(".mkv") == true + || it.name?.endsWith(".${Injekt.get().extension?.extension?.getFileExtension()?.first ?: "ts"}") == true + } + if (docFile != null) { + val uri = docFile.uri + val downloadedMimeType = when (docFile.extension) { + "mp4" -> MimeTypes.APPLICATION_MP4 + "mkv" -> MimeTypes.APPLICATION_MATROSKA + else -> MimeTypes.APPLICATION_MP4 + } + MediaItem.Builder().setUri(uri).setMimeType(downloadedMimeType).build() + } else { + snackString("File not found") + null + } } else { - downloadedMediaItem + snackString("Directory not found") + null } } + } else null + + mediaItem = if (downloadedMediaItem == null) { + val builder = MediaItem.Builder().setUri(video!!.file.url).setMimeType(mimeType) + Logger.log("url: ${video!!.file.url}") + Logger.log("mimeType: $mimeType") + builder.setSubtitleConfigurations(sub) + builder.build() + } else { + if (sub.isNotEmpty()) { + val addedSubsDownloadedMediaItem = downloadedMediaItem.buildUpon() + val addLanguage = sub[0].buildUpon().setLanguage("en").build() + addedSubsDownloadedMediaItem.setSubtitleConfigurations(listOf(addLanguage)) + episode.selectedSubtitle = 0 + addedSubsDownloadedMediaItem.build() + } else { + downloadedMediaItem + } + } val audioMediaItem = mutableListOf() audioLanguages.clear() @@ -1795,203 +1621,179 @@ class ExoplayerView : if (code == "all") code = "un" audioLanguages.add(Pair(it.lang, code)) audioMediaItem.add( - MediaItem - .Builder() + MediaItem.Builder() .setUri(it.url) .setMimeType(MimeTypes.AUDIO_UNKNOWN) .setTag(code) - .build(), + .build() ) } - val audioSources = - audioMediaItem - .map { mediaItem -> - if (mediaItem.localConfiguration - ?.uri - .toString() - .contains(".m3u8") - ) { - HlsMediaSource.Factory(cacheFactory).createMediaSource(mediaItem) - } else { - DefaultMediaSourceFactory(cacheFactory).createMediaSource(mediaItem) - } - }.toTypedArray() - val videoMediaSource = - DefaultMediaSourceFactory(cacheFactory) - .createMediaSource(mediaItem) + val audioSources = audioMediaItem.map { mediaItem -> + if (mediaItem.localConfiguration?.uri.toString().contains(".m3u8")) { + HlsMediaSource.Factory(cacheFactory).createMediaSource(mediaItem) + } else { + DefaultMediaSourceFactory(cacheFactory).createMediaSource(mediaItem) + } + }.toTypedArray() + val videoMediaSource = DefaultMediaSourceFactory(cacheFactory) + .createMediaSource(mediaItem) mediaSource = MergingMediaSource(videoMediaSource, *audioSources) - // Source + + //Source exoSource.setOnClickListener { sourceClick() } - // Quality Track + //Quality Track trackSelector = DefaultTrackSelector(this) - val parameters = - trackSelector - .buildUponParameters() - .setAllowVideoMixedMimeTypeAdaptiveness(true) - .setAllowVideoNonSeamlessAdaptiveness(true) - .setSelectUndeterminedTextLanguage(true) - .setAllowAudioMixedMimeTypeAdaptiveness(true) - .setAllowMultipleAdaptiveSelections(true) - .setPreferredTextLanguage(subtitle?.language ?: Locale.getDefault().language) - .setPreferredTextRoleFlags(C.ROLE_FLAG_SUBTITLE) - .setRendererDisabled(TRACK_TYPE_VIDEO, false) - .setRendererDisabled(TRACK_TYPE_AUDIO, false) - .setRendererDisabled(TRACK_TYPE_TEXT, false) - .setMaxVideoSize(1, 1) + val parameters = trackSelector.buildUponParameters() + .setAllowVideoMixedMimeTypeAdaptiveness(true) + .setAllowVideoNonSeamlessAdaptiveness(true) + .setSelectUndeterminedTextLanguage(true) + .setAllowAudioMixedMimeTypeAdaptiveness(true) + .setAllowMultipleAdaptiveSelections(true) + .setPreferredTextLanguage(subtitle?.language ?: Locale.getDefault().language) + .setPreferredTextRoleFlags(C.ROLE_FLAG_SUBTITLE) + .setRendererDisabled(TRACK_TYPE_VIDEO, false) + .setRendererDisabled(TRACK_TYPE_AUDIO, false) + .setRendererDisabled(TRACK_TYPE_TEXT, false) + .setMaxVideoSize(1, 1) // .setOverrideForType(TrackSelectionOverride(trackSelector, TRACK_TYPE_VIDEO)) - if (PrefManager.getVal(PrefName.SettingsPreferDub)) { + if (PrefManager.getVal(PrefName.SettingsPreferDub)) parameters.setPreferredAudioLanguage(Locale.getDefault().language) - } trackSelector.setParameters(parameters) if (playbackPosition != 0L && !changingServer && !PrefManager.getVal(PrefName.AlwaysContinue)) { - val time = - String.format( - "%02d:%02d:%02d", - TimeUnit.MILLISECONDS.toHours(playbackPosition), - TimeUnit.MILLISECONDS.toMinutes(playbackPosition) - - TimeUnit.HOURS.toMinutes( - TimeUnit.MILLISECONDS.toHours( - playbackPosition, - ), - ), - TimeUnit.MILLISECONDS.toSeconds(playbackPosition) - - TimeUnit.MINUTES.toSeconds( - TimeUnit.MILLISECONDS.toMinutes( - playbackPosition, - ), - ), + val time = String.format( + "%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(playbackPosition), + TimeUnit.MILLISECONDS.toMinutes(playbackPosition) - TimeUnit.HOURS.toMinutes( + TimeUnit.MILLISECONDS.toHours( + playbackPosition + ) + ), + TimeUnit.MILLISECONDS.toSeconds(playbackPosition) - TimeUnit.MINUTES.toSeconds( + TimeUnit.MILLISECONDS.toMinutes( + playbackPosition + ) ) - customAlertDialog().apply { - setTitle(getString(R.string.continue_from, time)) - setCancelable(false) - setPosButton(getString(R.string.yes)) { - buildExoplayer() - } - setNegButton(getString(R.string.no)) { - playbackPosition = 0L - buildExoplayer() - } - show() - } - } else { - buildExoplayer() - } + ) + val dialog = AlertDialog.Builder(this, R.style.MyPopup) + .setTitle(getString(R.string.continue_from, time)).apply { + setCancelable(false) + setPositiveButton(getString(R.string.yes)) { d, _ -> + buildExoplayer() + d.dismiss() + } + setNegativeButton(getString(R.string.no)) { d, _ -> + playbackPosition = 0L + buildExoplayer() + d.dismiss() + } + }.show() + dialog.window?.setDimAmount(0.8f) + } else buildExoplayer() } private fun buildExoplayer() { - // Player - val loadControl = - DefaultLoadControl - .Builder() - .setBackBuffer(1000 * 60 * 2, true) - .setBufferDurationsMs( - DEFAULT_MIN_BUFFER_MS, - DEFAULT_MAX_BUFFER_MS, - BUFFER_FOR_PLAYBACK_MS, - BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS, - ).build() + //Player + val loadControl = DefaultLoadControl.Builder() + .setBackBuffer(1000 * 60 * 2, true) + .setBufferDurationsMs( + DEFAULT_MIN_BUFFER_MS, + DEFAULT_MAX_BUFFER_MS, + BUFFER_FOR_PLAYBACK_MS, + BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS + ) + .build() hideSystemBars() val useExtensionDecoder = PrefManager.getVal(PrefName.UseAdditionalCodec) - val decoder = - if (useExtensionDecoder) { - DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER - } else { - DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF - } - val renderersFactory = - NextRenderersFactory(this) - .setEnableDecoderFallback(true) - .setExtensionRendererMode(decoder) + val decoder = if (useExtensionDecoder) { + DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER + } else { + DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF + } + val renderersFactory = NextRenderersFactory(this) + .setEnableDecoderFallback(true) + .setExtensionRendererMode(decoder) - exoPlayer = - ExoPlayer - .Builder(this, renderersFactory) - .setMediaSourceFactory(DefaultMediaSourceFactory(cacheFactory)) - .setTrackSelector(trackSelector) - .setLoadControl(loadControl) - .build() - .apply { - playWhenReady = true - this.playbackParameters = this@ExoplayerView.playbackParameters - setMediaSource(mediaSource) - prepare() - PrefManager - .getCustomVal( - "${media.id}_${media.anime!!.selectedEpisode}_max", - Long.MAX_VALUE, - ).takeIf { it != Long.MAX_VALUE } - ?.let { if (it <= playbackPosition) playbackPosition = max(0, it - 5) } - seekTo(playbackPosition) - } + exoPlayer = ExoPlayer.Builder(this, renderersFactory) + .setMediaSourceFactory(DefaultMediaSourceFactory(cacheFactory)) + .setTrackSelector(trackSelector) + .setLoadControl(loadControl) + .build().apply { + playWhenReady = true + this.playbackParameters = this@ExoplayerView.playbackParameters + setMediaSource(mediaSource) + prepare() + PrefManager.getCustomVal( + "${media.id}_${media.anime!!.selectedEpisode}_max", + Long.MAX_VALUE + ) + .takeIf { it != Long.MAX_VALUE } + ?.let { if (it <= playbackPosition) playbackPosition = max(0, it - 5) } + seekTo(playbackPosition) + } playerView.player = exoPlayer - exoPlayer.addListener( - object : Player.Listener { - var activeSubtitles = ArrayDeque(3) - var lastSubtitle: String? = null - var lastPosition: Long = 0 + exoPlayer.addListener(object : Player.Listener { + var activeSubtitles = ArrayDeque(3) + var lastSubtitle: String? = null + var lastPosition: Long = 0 - override fun onCues(cueGroup: CueGroup) { - if (PrefManager.getVal(PrefName.TextviewSubtitles)) { - exoSubtitleView.visibility = View.GONE - customSubtitleView.visibility = View.VISIBLE - val newCues = cueGroup.cues.map { it.text.toString() } + override fun onCues(cueGroup: CueGroup) { + if (PrefManager.getVal(PrefName.TextviewSubtitles)) { + exoSubtitleView.visibility = View.GONE + customSubtitleView.visibility = View.VISIBLE + val newCues = cueGroup.cues.map { it.text.toString() } - if (newCues.isEmpty()) { - customSubtitleView.text = "" - activeSubtitles.clear() - lastSubtitle = null - lastPosition = 0 - return - } - - val currentPosition = exoPlayer.currentPosition - - if ((lastSubtitle?.length - ?: 0) < 20 || (lastPosition != 0L && currentPosition - lastPosition > 1500) - ) { - activeSubtitles.clear() - } - - for (newCue in newCues) { - if (newCue !in activeSubtitles) { - if (activeSubtitles.size >= 2) { - activeSubtitles.removeLast() - } - activeSubtitles.addFirst(newCue) - lastSubtitle = newCue - lastPosition = currentPosition - } - } - - customSubtitleView.text = activeSubtitles.joinToString("\n") - } else { + if (newCues.isEmpty()) { customSubtitleView.text = "" - customSubtitleView.visibility = View.GONE - exoSubtitleView.visibility = View.VISIBLE + activeSubtitles.clear() + lastSubtitle = null + lastPosition = 0 + return } + + val currentPosition = exoPlayer.currentPosition + + if ((lastSubtitle?.length + ?: 0) < 20 || (lastPosition != 0L && currentPosition - lastPosition > 1500) + ) { + activeSubtitles.clear() + } + + for (newCue in newCues) { + if (newCue !in activeSubtitles) { + if (activeSubtitles.size >= 2) { + activeSubtitles.removeLast() + } + activeSubtitles.addFirst(newCue) + lastSubtitle = newCue + lastPosition = currentPosition + } + } + + customSubtitleView.text = activeSubtitles.joinToString("\n") + } else { + customSubtitleView.text = "" + customSubtitleView.visibility = View.GONE + exoSubtitleView.visibility = View.VISIBLE } - }, - ) + } + }) applySubtitleStyles(customSubtitleView) setupSubFormatting(playerView) try { val rightNow = Calendar.getInstance() - mediaSession = - MediaSession - .Builder(this, exoPlayer) - .setId(rightNow.timeInMillis.toString()) - .build() + mediaSession = MediaSession.Builder(this, exoPlayer) + .setId(rightNow.timeInMillis.toString()) + .build() } catch (e: Exception) { toast(e.toString()) } @@ -2005,11 +1807,10 @@ class ExoplayerView : } val isDisabled = (subtitle == null && hasExtSubtitles) - exoPlayer.trackSelectionParameters = - exoPlayer.trackSelectionParameters - .buildUpon() - .setTrackTypeDisabled(TRACK_TYPE_TEXT, isDisabled) - .build() + exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters + .buildUpon() + .setTrackTypeDisabled(TRACK_TYPE_TEXT, isDisabled) + .build() } private fun releasePlayer() { @@ -2025,6 +1826,7 @@ class ExoplayerView : DiscordServiceRunningSingleton.running = false stopService(stopIntent) } + } override fun onSaveInstanceState(outState: Bundle) { @@ -2042,22 +1844,18 @@ class ExoplayerView : media.selected!!.server = null PrefManager.setCustomVal( - "${media.id}_${media.anime!!.selectedEpisode}", - exoPlayer.currentPosition, + "${media.id}_${media.anime!!.selectedEpisode}", exoPlayer.currentPosition ) model.saveSelected(media.id, media.selected!!) model.onEpisodeClick( - media, - episode.number, - this.supportFragmentManager, - launch = false, + media, episode.number, this.supportFragmentManager, + launch = false ) } private fun subClick() { PrefManager.setCustomVal( - "${media.id}_${media.anime!!.selectedEpisode}", - exoPlayer.currentPosition, + "${media.id}_${media.anime!!.selectedEpisode}", exoPlayer.currentPosition ) model.saveSelected(media.id, media.selected!!) SubtitleDialogFragment().show(supportFragmentManager, "dialog") @@ -2073,7 +1871,7 @@ class ExoplayerView : if (exoPlayer.currentPosition > 5000) { PrefManager.setCustomVal( "${media.id}_${media.anime!!.selectedEpisode}", - exoPlayer.currentPosition, + exoPlayer.currentPosition ) } } @@ -2097,7 +1895,6 @@ class ExoplayerView : } private var wasPlaying = false - override fun onWindowFocusChanged(hasFocus: Boolean) { if (PrefManager.getVal(PrefName.FocusPause) && !epChanging) { if (isInitialized && !hasFocus) wasPlaying = exoPlayer.isPlaying @@ -2115,12 +1912,9 @@ class ExoplayerView : isPlayerPlaying = isPlaying playerView.keepScreenOn = isPlaying (exoPlay.drawable as Animatable?)?.start() - if (!this.isDestroyed) { - Glide - .with(this) - .load(if (isPlaying) R.drawable.anim_play_to_pause else R.drawable.anim_pause_to_play) - .into(exoPlay) - } + if (!this.isDestroyed) Glide.with(this) + .load(if (isPlaying) R.drawable.anim_play_to_pause else R.drawable.anim_pause_to_play) + .into(exoPlay) } } @@ -2128,7 +1922,7 @@ class ExoplayerView : super.onRenderedFirstFrame() PrefManager.setCustomVal( "${media.id}_${media.anime!!.selectedEpisode}_max", - exoPlayer.duration, + exoPlayer.duration ) val height = (exoPlayer.videoFormat ?: return).height val width = (exoPlayer.videoFormat ?: return).width @@ -2137,11 +1931,10 @@ class ExoplayerView : videoInfo.text = getString(R.string.video_quality, height) - if (exoPlayer.duration < playbackPosition) { + if (exoPlayer.duration < playbackPosition) exoPlayer.seekTo(0) - } - // if playbackPosition is within 92% of the episode length, reset it to 0 + //if playbackPosition is within 92% of the episode length, reset it to 0 if (playbackPosition > exoPlayer.duration.toFloat() * 0.92) { playbackPosition = 0 exoPlayer.seekTo(0) @@ -2152,25 +1945,20 @@ class ExoplayerView : lifecycleScope.launch(Dispatchers.IO) { model.loadTimeStamps( media.idMAL, - media.anime - ?.selectedEpisode - ?.trim() - ?.toIntOrNull(), + media.anime?.selectedEpisode?.trim()?.toIntOrNull(), dur / 1000, - PrefManager.getVal(PrefName.UseProxyForTimeStamps), + PrefManager.getVal(PrefName.UseProxyForTimeStamps) ) } } } - // Link Preloading + //Link Preloading private var preloading = false - private fun updateProgress() { if (isInitialized) { - if (exoPlayer.currentPosition.toFloat() / exoPlayer.duration > - PrefManager.getVal( - PrefName.WatchPercentage, + if (exoPlayer.currentPosition.toFloat() / exoPlayer.duration > PrefManager.getVal( + PrefName.WatchPercentage ) ) { preloading = true @@ -2178,150 +1966,134 @@ class ExoplayerView : val ep = episodes[episodeArr[currentEpisodeIndex + i]] ?: return@nextEpisode val selected = media.selected ?: return@nextEpisode lifecycleScope.launch(Dispatchers.IO) { - if (media.selected!!.server != null) { + if (media.selected!!.server != null) model.loadEpisodeSingleVideo(ep, selected, false) - } else { + else model.loadEpisodeVideos(ep, selected.sourceIndex, false) - } } } } } - if (!preloading) { - handler.postDelayed({ - updateProgress() - }, 2500) - } + if (!preloading) handler.postDelayed({ + updateProgress() + }, 2500) } - // TimeStamp Updating + //TimeStamp Updating private var currentTimeStamp: AniSkip.Stamp? = null private var skippedTimeStamps: MutableList = mutableListOf() - private fun updateTimeStamp() { if (isInitialized) { val playerCurrentTime = exoPlayer.currentPosition / 1000 - currentTimeStamp = - model.timeStamps.value?.find { timestamp -> - timestamp.interval.startTime < playerCurrentTime && - playerCurrentTime < (timestamp.interval.endTime - 1) - } + currentTimeStamp = model.timeStamps.value?.find { timestamp -> + timestamp.interval.startTime < playerCurrentTime + && playerCurrentTime < (timestamp.interval.endTime - 1) + } val new = currentTimeStamp - timeStampText.text = - if (new != null) { - fun disappearSkip() { - functionstarted = true + timeStampText.text = if (new != null) { + fun disappearSkip() { + functionstarted = true + skipTimeButton.visibility = View.VISIBLE + exoSkip.visibility = View.GONE + skipTimeText.text = new.skipType.getType() + skipTimeButton.setOnClickListener { + exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) + } + var timer: CountDownTimer? = null + fun cancelTimer() { + timer?.cancel() + timer = null + return + } + timer = object : CountDownTimer(5000, 1000) { + override fun onTick(millisUntilFinished: Long) { + if (new == null) { + skipTimeButton.visibility = View.GONE + exoSkip.isVisible = PrefManager.getVal(PrefName.SkipTime) > 0 + disappeared = false + functionstarted = false + cancelTimer() + } + } + + override fun onFinish() { + skipTimeButton.visibility = View.GONE + exoSkip.isVisible = PrefManager.getVal(PrefName.SkipTime) > 0 + disappeared = true + functionstarted = false + cancelTimer() + } + } + timer?.start() + + } + if (PrefManager.getVal(PrefName.ShowTimeStampButton)) { + + if (!functionstarted && !disappeared && PrefManager.getVal(PrefName.AutoHideTimeStamps)) { + disappearSkip() + } else if (!PrefManager.getVal(PrefName.AutoHideTimeStamps)) { skipTimeButton.visibility = View.VISIBLE exoSkip.visibility = View.GONE skipTimeText.text = new.skipType.getType() skipTimeButton.setOnClickListener { exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) } - var timer: CountDownTimer? = null + } - fun cancelTimer() { - timer?.cancel() - timer = null - return - } - timer = - object : CountDownTimer(5000, 1000) { - override fun onTick(millisUntilFinished: Long) { - if (new == null) { - skipTimeButton.visibility = View.GONE - exoSkip.isVisible = - PrefManager.getVal(PrefName.SkipTime) > 0 - disappeared = false - functionstarted = false - cancelTimer() - } - } - - override fun onFinish() { - skipTimeButton.visibility = View.GONE - exoSkip.isVisible = - PrefManager.getVal(PrefName.SkipTime) > 0 - disappeared = true - functionstarted = false - cancelTimer() - } - } - timer?.start() - } - if (PrefManager.getVal(PrefName.ShowTimeStampButton)) { - if (!functionstarted && !disappeared && PrefManager.getVal(PrefName.AutoHideTimeStamps)) { - disappearSkip() - } else if (!PrefManager.getVal(PrefName.AutoHideTimeStamps)) { - skipTimeButton.visibility = View.VISIBLE - exoSkip.visibility = View.GONE - skipTimeText.text = new.skipType.getType() - skipTimeButton.setOnClickListener { - exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) - } - } - } - if (PrefManager.getVal(PrefName.AutoSkipOPED) && - (new.skipType == "op" || new.skipType == "ed") && - !skippedTimeStamps.contains(new) - ) { - exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) - skippedTimeStamps.add(new) - } - if (PrefManager.getVal(PrefName.AutoSkipRecap) && - new.skipType == "recap" && - !skippedTimeStamps.contains( - new, - ) - ) { - exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) - skippedTimeStamps.add(new) - } - new.skipType.getType() - } else { - disappeared = false - functionstarted = false - skipTimeButton.visibility = View.GONE - exoSkip.isVisible = PrefManager.getVal(PrefName.SkipTime) > 0 - "" } + if (PrefManager.getVal(PrefName.AutoSkipOPED) && (new.skipType == "op" || new.skipType == "ed") + && !skippedTimeStamps.contains(new) + ) { + exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) + skippedTimeStamps.add(new) + } + if (PrefManager.getVal(PrefName.AutoSkipRecap) && new.skipType == "recap" && !skippedTimeStamps.contains( + new + ) + ) { + exoPlayer.seekTo((new.interval.endTime * 1000).toLong()) + skippedTimeStamps.add(new) + } + new.skipType.getType() + } else { + disappeared = false + functionstarted = false + skipTimeButton.visibility = View.GONE + exoSkip.isVisible = PrefManager.getVal(PrefName.SkipTime) > 0 + "" + } } handler.postDelayed({ updateTimeStamp() }, 500) } - fun onSetTrackGroupOverride( - trackGroup: Tracks.Group, - type: @C.TrackType Int, - index: Int = 0, - ) { + fun onSetTrackGroupOverride(trackGroup: Tracks.Group, type: @C.TrackType Int, index: Int = 0) { val isDisabled = trackGroup.getTrackFormat(0).language == "none" - exoPlayer.trackSelectionParameters = - exoPlayer.trackSelectionParameters - .buildUpon() - .setTrackTypeDisabled(TRACK_TYPE_TEXT, isDisabled) - .setOverrideForType( - TrackSelectionOverride(trackGroup.mediaTrackGroup, index), - ).build() + exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters + .buildUpon() + .setTrackTypeDisabled(TRACK_TYPE_TEXT, isDisabled) + .setOverrideForType( + TrackSelectionOverride(trackGroup.mediaTrackGroup, index) + ) + .build() if (type == TRACK_TYPE_TEXT) { setupSubFormatting(playerView) applySubtitleStyles(customSubtitleView) } - playerView.subtitleView?.alpha = - when (isDisabled) { - false -> PrefManager.getVal(PrefName.SubAlpha) - true -> 0f - } + playerView.subtitleView?.alpha = when (isDisabled) { + false -> PrefManager.getVal(PrefName.SubAlpha) + true -> 0f + } } - private val dummyTrack = - Tracks.Group( - TrackGroup("Dummy Track", Format.Builder().apply { setLanguage("none") }.build()), - true, - intArrayOf(1), - booleanArrayOf(false), - ) + private val dummyTrack = Tracks.Group( + TrackGroup("Dummy Track", Format.Builder().apply { setLanguage("none") }.build()), + true, + intArrayOf(1), + booleanArrayOf(false) + ) override fun onTracksChanged(tracks: Tracks) { val audioTracks: ArrayList = arrayListOf() @@ -2329,7 +2101,7 @@ class ExoplayerView : tracks.groups.forEach { println( "Track__: $it\nTrack__: ${it.length}\nTrack__: ${it.isSelected}\n" + - "Track__: ${it.type}\nTrack__: ${it.mediaTrackGroup.id}", + "Track__: ${it.type}\nTrack__: ${it.mediaTrackGroup.id}" ) when (it.type) { TRACK_TYPE_AUDIO -> { @@ -2358,33 +2130,31 @@ class ExoplayerView : } } - private val onChangeSettings = - registerForActivityResult( - ActivityResultContracts.StartActivityForResult(), - ) { _: ActivityResult -> - if (!hasExtSubtitles) { - exoPlayer.currentTracks.groups.forEach { trackGroup -> - when (trackGroup.type) { - TRACK_TYPE_TEXT -> { - if (PrefManager.getVal(PrefName.Subtitles)) { - onSetTrackGroupOverride(trackGroup, TRACK_TYPE_TEXT) - } else { - onSetTrackGroupOverride(dummyTrack, TRACK_TYPE_TEXT) - } + private val onChangeSettings = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { _: ActivityResult -> + if (!hasExtSubtitles) { + exoPlayer.currentTracks.groups.forEach { trackGroup -> + when (trackGroup.type) { + TRACK_TYPE_TEXT -> { + if (PrefManager.getVal(PrefName.Subtitles)) { + onSetTrackGroupOverride(trackGroup, TRACK_TYPE_TEXT) + } else { + onSetTrackGroupOverride(dummyTrack, TRACK_TYPE_TEXT) } - - else -> {} } + + else -> {} } } - if (isInitialized) exoPlayer.play() } + if (isInitialized) exoPlayer.play() + } override fun onPlayerError(error: PlaybackException) { when (error.errorCode) { PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS, - PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, - -> { + PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED -> { toast("Source Exception : ${error.message}") isPlayerPlaying = true sourceClick() @@ -2398,7 +2168,6 @@ class ExoplayerView : } private var isBuffering = true - override fun onPlaybackStateChanged(playbackState: Int) { if (playbackState == ExoPlayer.STATE_READY) { exoPlayer.play() @@ -2409,30 +2178,24 @@ class ExoplayerView : } isBuffering = playbackState == Player.STATE_BUFFERING if (playbackState == Player.STATE_ENDED && PrefManager.getVal(PrefName.AutoPlay)) { - if (interacted) { - exoNext.performClick() - } else { - toast(getString(R.string.autoplay_cancelled)) - } + if (interacted) exoNext.performClick() + else toast(getString(R.string.autoplay_cancelled)) } super.onPlaybackStateChanged(playbackState) } private fun updateAniProgress() { val incognito: Boolean = PrefManager.getVal(PrefName.Incognito) - val episodeEnd = - exoPlayer.currentPosition / episodeLength > - PrefManager.getVal( - PrefName.WatchPercentage, - ) + val episodeEnd = exoPlayer.currentPosition / episodeLength > PrefManager.getVal( + PrefName.WatchPercentage + ) val episode0 = currentEpisodeIndex == 0 && PrefManager.getVal(PrefName.ChapterZeroPlayer) if (!incognito && (episodeEnd || episode0) && Anilist.userid != null - ) { + ) if (PrefManager.getCustomVal( "${media.id}_save_progress", - true, - ) && - (if (media.isAdult) PrefManager.getVal(PrefName.UpdateForHPlayer) else true) + true + ) && (if (media.isAdult) PrefManager.getVal(PrefName.UpdateForHPlayer) else true) ) { if (episode0) { updateProgress(media, "0") @@ -2442,30 +2205,21 @@ class ExoplayerView : } } } - } } - private fun nextEpisode( - toast: Boolean = true, - runnable: ((Int) -> Unit), - ) { + private fun nextEpisode(toast: Boolean = true, runnable: ((Int) -> Unit)) { var isFiller = true var i = 1 while (isFiller) { if (episodeArr.size > currentEpisodeIndex + i) { isFiller = - if (PrefManager.getVal(PrefName.AutoSkipFiller)) { - episodes[episodeArr[currentEpisodeIndex + i]]?.filler - ?: false - } else { - false - } + if (PrefManager.getVal(PrefName.AutoSkipFiller)) episodes[episodeArr[currentEpisodeIndex + i]]?.filler + ?: false else false if (!isFiller) runnable.invoke(i) i++ } else { - if (toast) { + if (toast) toast(getString(R.string.no_next_episode)) - } isFiller = false } } @@ -2508,7 +2262,7 @@ class ExoplayerView : if (subtitle != null) shareVideo.putExtra("subtitle", subtitleUrl) shareVideo.putExtra( "title", - media.userPreferredName + " : Ep " + episodeTitleArr[currentEpisodeIndex], + media.userPreferredName + " : Ep " + episodeTitleArr[currentEpisodeIndex] ) shareVideo.putExtra("poster", episode.thumb?.url ?: media.cover) val headers = Bundle() @@ -2541,7 +2295,7 @@ class ExoplayerView : PictureInPictureParams .Builder() .setAspectRatio(aspectRatio) - .build(), + .build() ) } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { enterPictureInPictureMode() @@ -2562,7 +2316,7 @@ class ExoplayerView : if (isInitialized) { PrefManager.setCustomVal( "${media.id}_${episode.number}", - exoPlayer.currentPosition, + exoPlayer.currentPosition ) if (wasPlaying) exoPlayer.play() } @@ -2583,65 +2337,59 @@ class ExoplayerView : @RequiresApi(Build.VERSION_CODES.O) override fun onPictureInPictureModeChanged( isInPictureInPictureMode: Boolean, - newConfig: Configuration, + newConfig: Configuration ) { onPiPChanged(isInPictureInPictureMode) super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) } - private val keyMap: MutableMap Unit)?> = - mutableMapOf( - KEYCODE_DPAD_RIGHT to null, - KEYCODE_DPAD_LEFT to null, - KEYCODE_SPACE to { exoPlay.performClick() }, - KEYCODE_N to { exoNext.performClick() }, - KEYCODE_B to { exoPrev.performClick() }, - ) + private val keyMap: MutableMap Unit)?> = mutableMapOf( + KEYCODE_DPAD_RIGHT to null, + KEYCODE_DPAD_LEFT to null, + KEYCODE_SPACE to { exoPlay.performClick() }, + KEYCODE_N to { exoNext.performClick() }, + KEYCODE_B to { exoPrev.performClick() } + ) - override fun dispatchKeyEvent(event: KeyEvent): Boolean = - if (keyMap.containsKey(event.keyCode)) { + override fun dispatchKeyEvent(event: KeyEvent): Boolean { + return if (keyMap.containsKey(event.keyCode)) { (event.action == ACTION_UP).also { if (isInitialized && it) keyMap[event.keyCode]?.invoke() } } else { super.dispatchKeyEvent(event) } + } + private fun startCastPlayer() { if (!isCastApiAvailable) { snackString("Cast API not available") return } - // make sure mediaItem is initialized and castPlayer is not null + //make sure mediaItem is initialized and castPlayer is not null if (!this::mediaItem.isInitialized || castPlayer == null) return castPlayer?.setMediaItem(mediaItem) castPlayer?.prepare() playerView.player = castPlayer exoPlayer.stop() - castPlayer?.addListener( - object : Player.Listener { - // if the player is paused changed, we want to update the UI - override fun onPlayWhenReadyChanged( - playWhenReady: Boolean, - reason: Int, - ) { - super.onPlayWhenReadyChanged(playWhenReady, reason) - if (playWhenReady) { - (exoPlay.drawable as Animatable?)?.start() - Glide - .with(this@ExoplayerView) - .load(R.drawable.anim_play_to_pause) - .into(exoPlay) - } else { - (exoPlay.drawable as Animatable?)?.start() - Glide - .with(this@ExoplayerView) - .load(R.drawable.anim_pause_to_play) - .into(exoPlay) - } + castPlayer?.addListener(object : Player.Listener { + //if the player is paused changed, we want to update the UI + override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) { + super.onPlayWhenReadyChanged(playWhenReady, reason) + if (playWhenReady) { + (exoPlay.drawable as Animatable?)?.start() + Glide.with(this@ExoplayerView) + .load(R.drawable.anim_play_to_pause) + .into(exoPlay) + } else { + (exoPlay.drawable as Animatable?)?.start() + Glide.with(this@ExoplayerView) + .load(R.drawable.anim_pause_to_play) + .into(exoPlay) } - }, - ) + } + }) } private fun startExoPlayer() { @@ -2661,14 +2409,14 @@ class ExoplayerView : startExoPlayer() } + @SuppressLint("ViewConstructor") class ExtendedTimeBar( context: Context, - attrs: AttributeSet?, + attrs: AttributeSet? ) : DefaultTimeBar(context, attrs) { private var enabled = false private var forceDisabled = false - override fun setEnabled(enabled: Boolean) { this.enabled = enabled super.setEnabled(!forceDisabled && this.enabled) @@ -2682,6 +2430,7 @@ class ExoplayerView : } class CustomCastButton : MediaRouteButton { + private var castCallback: (() -> Unit)? = null fun setCastCallback(castCallback: () -> Unit) { @@ -2695,14 +2444,15 @@ class CustomCastButton : MediaRouteButton { constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super( context, attrs, - defStyleAttr, + defStyleAttr ) - override fun performClick(): Boolean = - if (PrefManager.getVal(PrefName.UseInternalCast)) { + override fun performClick(): Boolean { + return if (PrefManager.getVal(PrefName.UseInternalCast)) { super.performClick() } else { castCallback?.let { it() } true } -} + } +} \ 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 ddf98974..a76d44a4 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadAdapter.kt @@ -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(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) } 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 63ef7408..6b7eb6bc 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaReadFragment.kt @@ -474,7 +474,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener { scanlator = chapter.scanlator ?: "Unknown", imageData = images, sourceMedia = media, - retries = 25, + retries = 2, simultaneousDownloads = 2 ) diff --git a/app/src/main/java/ani/dantotsu/others/CrashActivity.kt b/app/src/main/java/ani/dantotsu/others/CrashActivity.kt index c8a0af8b..c410d687 100644 --- a/app/src/main/java/ani/dantotsu/others/CrashActivity.kt +++ b/app/src/main/java/ani/dantotsu/others/CrashActivity.kt @@ -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 { topMargin = statusBarHeight diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsAnimeActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsAnimeActivity.kt index 73f90595..2a5c6aee 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsAnimeActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsAnimeActivity.kt @@ -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.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() } ), @@ -137,4 +143,4 @@ class SettingsAnimeActivity : AppCompatActivity() { } } -} +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt index f0bf91d0..8cfa7160 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsCommonActivity.kt @@ -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,27 +62,23 @@ class SettingsCommonActivity : AppCompatActivity() { registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri -> if (uri != null) { try { - val jsonString = - contentResolver.openInputStream(uri)?.readBytes() - ?: throw Exception("Error reading file") + 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 { - PreferenceKeystore.decryptWithPassword( - password, - encrypted, - salt, - ) - } catch (e: Exception) { - toast(getString(R.string.incorrect_password)) - return@passwordAlertDialog - } + val decryptedJson = try { + PreferenceKeystore.decryptWithPassword( + password, encrypted, salt + ) + } catch (e: Exception) { + toast(getString(R.string.incorrect_password)) + return@passwordAlertDialog + } if (PreferencePackager.unpack(decryptedJson)) restartApp() } else { toast(getString(R.string.password_cannot_be_empty)) @@ -103,6 +100,7 @@ class SettingsCommonActivity : AppCompatActivity() { launcher = LauncherWrapper(this, contract) binding.apply { + settingsCommonLayout.updateLayoutParams { topMargin = statusBarHeight bottomMargin = navBarHeight @@ -110,30 +108,27 @@ class SettingsCommonActivity : AppCompatActivity() { commonSettingsBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() } - val exDns = - listOf( - "None", - "Cloudflare", - "Google", - "AdGuard", - "Quad9", - "AliDNS", - "DNSPod", - "360", - "Quad101", - "Mullvad", - "Controld", - "Njalla", - "Shecan", - "Libre", - ) + val exDns = listOf( + "None", + "Cloudflare", + "Google", + "AdGuard", + "Quad9", + "AliDNS", + "DNSPod", + "360", + "Quad101", + "Mullvad", + "Controld", + "Njalla", + "Shecan", + "Libre" + ) 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,287 +136,283 @@ class SettingsCommonActivity : AppCompatActivity() { restartApp() } - settingsRecyclerView.adapter = - SettingsAdapter( - arrayListOf( - Settings( - type = 1, - name = getString(R.string.ui_settings), - desc = getString(R.string.ui_settings_desc), - icon = R.drawable.ic_round_auto_awesome_24, - onClick = { - startActivity( - Intent( - context, - UserInterfaceSettingsActivity::class.java, - ), + settingsRecyclerView.adapter = SettingsAdapter( + arrayListOf( + Settings( + type = 1, + name = getString(R.string.ui_settings), + desc = getString(R.string.ui_settings_desc), + icon = R.drawable.ic_round_auto_awesome_24, + onClick = { + startActivity( + Intent( + context, + UserInterfaceSettingsActivity::class.java ) - }, - isActivity = true, - ), - Settings( - type = 1, - name = getString(R.string.download_manager_select), - desc = getString(R.string.download_manager_select_desc), - icon = R.drawable.ic_download_24, - onClick = { - val managers = arrayOf("Default", "1DM", "ADM") - customAlertDialog().apply { - setTitle(getString(R.string.download_manager)) - singleChoiceItems( - managers, - PrefManager.getVal(PrefName.DownloadManager), - ) { count -> - PrefManager.setVal(PrefName.DownloadManager, count) - } - show() + ) + }, + 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, + name = getString(R.string.download_manager_select), + desc = getString(R.string.download_manager_select_desc), + icon = R.drawable.ic_download_24, + onClick = { + val managers = arrayOf("Default", "1DM", "ADM") + customAlertDialog().apply { + setTitle(getString(R.string.download_manager)) + singleChoiceItems( + managers, + PrefManager.getVal(PrefName.DownloadManager) + ) { count -> + PrefManager.setVal(PrefName.DownloadManager, count) } - }, - ), - Settings( - type = 1, - name = getString(R.string.app_lock), - desc = getString(R.string.app_lock_desc), - icon = R.drawable.ic_round_lock_open_24, - onClick = { - customAlertDialog().apply { - val view = DialogSetPasswordBinding.inflate(layoutInflater) - setTitle(R.string.app_lock) - setCustomView(view.root) - setPosButton(R.string.ok) { - if (view.forgotPasswordCheckbox.isChecked) { - PrefManager.setVal(PrefName.OverridePassword, true) - } - val password = view.passwordInput.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 + show() + } + } + ), + Settings( + type = 1, + name = getString(R.string.app_lock), + desc = getString(R.string.app_lock_desc), + icon = R.drawable.ic_round_lock_open_24, + onClick = { + customAlertDialog().apply { + val view = DialogSetPasswordBinding.inflate(layoutInflater) + setTitle(R.string.app_lock) + setCustomView(view.root) + setPosButton(R.string.ok) { + if (view.forgotPasswordCheckbox.isChecked) { + PrefManager.setVal(PrefName.OverridePassword, true) + } + val password = view.passwordInput.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 - if (canBiometricPrompt) { - val biometricPrompt = - BiometricPromptUtils.createBiometricPrompt( - this@SettingsCommonActivity - ) { _ -> - val token = UUID.randomUUID().toString() - PrefManager.setVal( - PrefName.BiometricToken, - token, - ) - toast(R.string.success) - } - val promptInfo = - BiometricPromptUtils.createPromptInfo(this@SettingsCommonActivity) - biometricPrompt.authenticate(promptInfo) - } + if (canBiometricPrompt) { + val biometricPrompt = + BiometricPromptUtils.createBiometricPrompt(this@SettingsCommonActivity) { _ -> + val token = UUID.randomUUID().toString() + PrefManager.setVal( + PrefName.BiometricToken, + token + ) + toast(R.string.success) + } + val promptInfo = + BiometricPromptUtils.createPromptInfo(this@SettingsCommonActivity) + biometricPrompt.authenticate(promptInfo) + } + + } else { + PrefManager.setVal(PrefName.BiometricToken, "") + toast(R.string.success) + } + } else { + toast(R.string.password_mismatch) + } + } + setNegButton(R.string.cancel) + setNeutralButton(R.string.remove) { + PrefManager.setVal(PrefName.AppPassword, "") + PrefManager.setVal(PrefName.BiometricToken, "") + PrefManager.setVal(PrefName.OverridePassword, false) + toast(R.string.success) + } + setOnShowListener { + view.passwordInput.requestFocus() + val canAuthenticate = + BiometricManager.from(applicationContext).canAuthenticate( + BiometricManager.Authenticators.BIOMETRIC_WEAK + ) == BiometricManager.BIOMETRIC_SUCCESS + view.biometricCheckbox.isVisible = canAuthenticate + view.biometricCheckbox.isChecked = + PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty() + view.forgotPasswordCheckbox.isChecked = + PrefManager.getVal(PrefName.OverridePassword) + } + show() + } + } + + ), + Settings( + type = 1, + name = getString(R.string.backup_restore), + desc = getString(R.string.backup_restore_desc), + icon = R.drawable.backup_restore, + onClick = { + StoragePermissions.downloadsPermission(context) + val selectedArray = mutableListOf(false) + val filteredLocations = Location.entries.filter { it.exportable } + 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.toBooleanArray() + ) { _, which, isChecked -> + selectedArray[which] = isChecked + }.setPositiveButton(R.string.button_restore) { dialog, _ -> + openDocumentLauncher.launch(arrayOf("*/*")) + dialog.dismiss() + }.setNegativeButton(R.string.button_backup) { dialog, _ -> + if (!selectedArray.contains(true)) { + toast(R.string.no_location_selected) + return@setNegativeButton + } + dialog.dismiss() + val selected = + filteredLocations.filterIndexed { index, _ -> selectedArray[index] } + if (selected.contains(Location.Protected)) { + passwordAlertDialog(true) { password -> + if (password != null) { + savePrefsToDownloads( + "DantotsuSettings", + PrefManager.exportAllPrefs(selected), + context, + password + ) } else { - PrefManager.setVal(PrefName.BiometricToken, "") - toast(R.string.success) + toast(R.string.password_cannot_be_empty) } - } else { - toast(R.string.password_mismatch) } + } else { + savePrefsToDownloads( + "DantotsuSettings", + PrefManager.exportAllPrefs(selected), + context, + null + ) } - setNegButton(R.string.cancel) - setNeutralButton(R.string.remove) { - PrefManager.setVal(PrefName.AppPassword, "") - PrefManager.setVal(PrefName.BiometricToken, "") - PrefManager.setVal(PrefName.OverridePassword, false) - toast(R.string.success) - } - setOnShowListener { - view.passwordInput.requestFocus() - val canAuthenticate = - BiometricManager.from(applicationContext) - .canAuthenticate( - BiometricManager.Authenticators.BIOMETRIC_WEAK, - ) == BiometricManager.BIOMETRIC_SUCCESS - view.biometricCheckbox.isVisible = canAuthenticate - view.biometricCheckbox.isChecked = - PrefManager.getVal(PrefName.BiometricToken, "") - .isNotEmpty() - view.forgotPasswordCheckbox.isChecked = - PrefManager.getVal(PrefName.OverridePassword) - } - show() - } - }, - ), - Settings( - type = 1, - name = getString(R.string.backup_restore), - desc = getString(R.string.backup_restore_desc), - icon = R.drawable.backup_restore, - onClick = { - StoragePermissions.downloadsPermission(context) - val filteredLocations = Location.entries.filter { it.exportable } - val selectedArray = BooleanArray(filteredLocations.size) { false } - context.customAlertDialog().apply { - setTitle(R.string.backup_restore) - multiChoiceItems( - filteredLocations.map { it.name }.toTypedArray(), - selectedArray, - ) { updatedSelection -> - for (i in updatedSelection.indices) { - selectedArray[i] = updatedSelection[i] - } - } - setPosButton(R.string.button_restore) { - openDocumentLauncher.launch(arrayOf("*/*")) - } - setNegButton(R.string.button_backup) { - if (!selectedArray.contains(true)) { - toast(R.string.no_location_selected) - return@setNegButton - } - val selected = - filteredLocations.filterIndexed { index, _ -> selectedArray[index] } - if (selected.contains(Location.Protected)) { - passwordAlertDialog(true) { password -> - if (password != null) { - savePrefsToDownloads( - "DantotsuSettings", - PrefManager.exportAllPrefs(selected), - context, - password, - ) - } else { - toast(R.string.password_cannot_be_empty) - } - } - } else { - savePrefsToDownloads( - "DantotsuSettings", - PrefManager.exportAllPrefs(selected), - context, - null, - ) - } - } - setNeutralButton(R.string.cancel) {} - show() - } - }, - ), - Settings( - type = 1, - name = getString(R.string.change_download_location), - desc = getString(R.string.change_download_location_desc), - icon = R.drawable.ic_round_source_24, - onClick = { - context.customAlertDialog().apply { - setTitle(R.string.change_download_location) - setMessage(R.string.download_location_msg) - setPosButton(R.string.ok) { - val oldUri = - PrefManager.getVal(PrefName.DownloadsDir) - launcher.registerForCallback { success -> - if (success) { - toast(getString(R.string.please_wait)) - val newUri = - PrefManager.getVal(PrefName.DownloadsDir) - GlobalScope.launch(Dispatchers.IO) { - Injekt.get().moveDownloadsDir( - context, - Uri.parse(oldUri), - Uri.parse(newUri), - ) { finished, message -> - if (finished) { - toast(getString(R.string.success)) - } else { - toast(message) - } + }.setNeutralButton(R.string.cancel) { dialog, _ -> + dialog.dismiss() + }.create() + dialog.window?.setDimAmount(0.8f) + dialog.show() + }, + ), + Settings( + type = 1, + name = getString(R.string.change_download_location), + desc = getString(R.string.change_download_location_desc), + icon = R.drawable.ic_round_source_24, + onClick = { + context.customAlertDialog().apply { + setTitle(R.string.change_download_location) + setMessage(R.string.download_location_msg) + setPosButton(R.string.ok) { + val oldUri = PrefManager.getVal(PrefName.DownloadsDir) + launcher.registerForCallback { success -> + if (success) { + toast(getString(R.string.please_wait)) + val newUri = + PrefManager.getVal(PrefName.DownloadsDir) + GlobalScope.launch(Dispatchers.IO) { + Injekt.get().moveDownloadsDir( + context, Uri.parse(oldUri), Uri.parse(newUri) + ) { finished, message -> + if (finished) { + toast(getString(R.string.success)) + } else { + toast(message) } } - } else { - toast(getString(R.string.error)) } + } else { + toast(getString(R.string.error)) } - launcher.launch() } - setNegButton(R.string.cancel) - show() + launcher.launch() } - }, - ), - Settings( - type = 2, - name = getString(R.string.always_continue_content), - desc = getString(R.string.always_continue_content_desc), - icon = R.drawable.ic_round_delete_24, - isChecked = PrefManager.getVal(PrefName.ContinueMedia), - switch = { isChecked, _ -> - PrefManager.setVal(PrefName.ContinueMedia, isChecked) - }, - ), - Settings( - type = 2, - name = getString(R.string.hide_private), - desc = getString(R.string.hide_private_desc), - icon = R.drawable.ic_round_remove_red_eye_24, - isChecked = PrefManager.getVal(PrefName.HidePrivate), - switch = { isChecked, _ -> - PrefManager.setVal(PrefName.HidePrivate, isChecked) - restartApp() - }, - ), - Settings( - type = 2, - name = getString(R.string.search_source_list), - desc = getString(R.string.search_source_list_desc), - icon = R.drawable.ic_round_search_sources_24, - isChecked = PrefManager.getVal(PrefName.SearchSources), - switch = { isChecked, _ -> - PrefManager.setVal(PrefName.SearchSources, isChecked) - }, - ), - Settings( - type = 2, - name = getString(R.string.recentlyListOnly), - desc = getString(R.string.recentlyListOnly_desc), - icon = R.drawable.ic_round_new_releases_24, - isChecked = PrefManager.getVal(PrefName.RecentlyListOnly), - switch = { isChecked, _ -> - PrefManager.setVal(PrefName.RecentlyListOnly, isChecked) - }, - ), - Settings( - type = 2, - name = getString(R.string.adult_only_content), - desc = getString(R.string.adult_only_content_desc), - icon = R.drawable.ic_round_nsfw_24, - isChecked = PrefManager.getVal(PrefName.AdultOnly), - switch = { isChecked, _ -> - PrefManager.setVal(PrefName.AdultOnly, isChecked) - restartApp() - }, - isVisible = Anilist.adult, - ), + setNegButton(R.string.cancel) + show() + } + } + ), + Settings( + type = 2, + name = getString(R.string.always_continue_content), + desc = getString(R.string.always_continue_content_desc), + icon = R.drawable.ic_round_delete_24, + isChecked = PrefManager.getVal(PrefName.ContinueMedia), + switch = { isChecked, _ -> + PrefManager.setVal(PrefName.ContinueMedia, isChecked) + } + ), + Settings( + type = 2, + name = getString(R.string.hide_private), + desc = getString(R.string.hide_private_desc), + icon = R.drawable.ic_round_remove_red_eye_24, + isChecked = PrefManager.getVal(PrefName.HidePrivate), + switch = { isChecked, _ -> + PrefManager.setVal(PrefName.HidePrivate, isChecked) + restartApp() + } + ), + Settings( + type = 2, + name = getString(R.string.search_source_list), + desc = getString(R.string.search_source_list_desc), + icon = R.drawable.ic_round_search_sources_24, + isChecked = PrefManager.getVal(PrefName.SearchSources), + switch = { isChecked, _ -> + PrefManager.setVal(PrefName.SearchSources, isChecked) + } + ), + Settings( + type = 2, + name = getString(R.string.recentlyListOnly), + desc = getString(R.string.recentlyListOnly_desc), + icon = R.drawable.ic_round_new_releases_24, + isChecked = PrefManager.getVal(PrefName.RecentlyListOnly), + switch = { isChecked, _ -> + PrefManager.setVal(PrefName.RecentlyListOnly, isChecked) + } + ), + Settings( + type = 2, + name = getString(R.string.adult_only_content), + desc = getString(R.string.adult_only_content_desc), + icon = R.drawable.ic_round_nsfw_24, + isChecked = PrefManager.getVal(PrefName.AdultOnly), + switch = { isChecked, _ -> + PrefManager.setVal(PrefName.AdultOnly, isChecked) + restartApp() + }, + isVisible = Anilist.adult + ), ) + ) settingsRecyclerView.apply { layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) setHasFixedSize(true) } - var previousStart: View = - when (PrefManager.getVal(PrefName.DefaultStartUpTab)) { - 0 -> uiSettingsAnime - 1 -> uiSettingsHome - 2 -> uiSettingsManga - else -> uiSettingsHome - } + var previousStart: View = when (PrefManager.getVal(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 = - getString(R.string.enter_password_to_decrypt_file) - } + 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() } + } -} + +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt index f1225ed4..ae3f08f5 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsNotificationActivity.kt @@ -128,27 +128,26 @@ class SettingsNotificationActivity : AppCompatActivity() { PrefManager.getVal>(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]) { - filteredTypes.add(type) - } else { - filteredTypes.remove(type) - } + ) { _, 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( + val selected = + PrefManager.getVal(PrefName.AnilistNotificationInterval) + val dialog = AlertDialog.Builder(context, R.style.MyPopup) + .setTitle(R.string.subscriptions_checking_time) + .setSingleChoiceItems( aItems.toTypedArray(), - PrefManager.getVal(PrefName.AnilistNotificationInterval) - ) { i -> + 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( + val selected = + PrefManager.getVal(PrefName.CommentNotificationInterval) + val dialog = AlertDialog.Builder(context, R.style.MyPopup) + .setTitle(R.string.subscriptions_checking_time) + .setSingleChoiceItems( cItems.toTypedArray(), - PrefManager.getVal(PrefName.CommentNotificationInterval) - ) { i -> + 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() @@ -270,4 +277,4 @@ class SettingsNotificationActivity : AppCompatActivity() { } } } -} +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsThemeActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsThemeActivity.kt index 648c26bd..8133640a 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsThemeActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsThemeActivity.kt @@ -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( diff --git a/app/src/main/java/ani/dantotsu/settings/SubscriptionsBottomDialog.kt b/app/src/main/java/ani/dantotsu/settings/SubscriptionsBottomDialog.kt index 188da9d3..9fa7552e 100644 --- a/app/src/main/java/ani/dantotsu/settings/SubscriptionsBottomDialog.kt +++ b/app/src/main/java/ani/dantotsu/settings/SubscriptionsBottomDialog.kt @@ -52,15 +52,14 @@ class SubscriptionsBottomDialog : BottomSheetDialogFragment() { } groupedSubscriptions.forEach { (parserName, mediaList) -> - adapter.add( - SubscriptionSource( - parserName, - mediaList.toMutableList(), - adapter, - getParserIcon(parserName) - ) { group -> - adapter.remove(group) - }) + adapter.add(SubscriptionSource( + parserName, + mediaList.toMutableList(), + adapter, + getParserIcon(parserName) + ) { group -> + adapter.remove(group) + }) } } diff --git a/app/src/main/res/layout/dialog_layout.xml b/app/src/main/res/layout/dialog_layout.xml index 3c9df3b8..3db06395 100644 --- a/app/src/main/res/layout/dialog_layout.xml +++ b/app/src/main/res/layout/dialog_layout.xml @@ -8,7 +8,7 @@ android:padding="16dp"> @@ -160,8 +160,8 @@ android:orientation="horizontal"> - - - - - - - - - + tools:text="number" />