From 7592c621d04858869e704589e20b1cabaa6d2133 Mon Sep 17 00:00:00 2001 From: jmir1 Date: Wed, 12 May 2021 19:32:56 +0200 Subject: [PATCH] anime player update! -added double tap to skip 10 seconds forwards/backwards -added skip 85 seconds button -added next and previous episode buttons -TODO: those buttons need to account for different episode sorting -TODO: next and previous buttons should be greyed out when there is no next/previous episode --- app/build.gradle.kts | 3 + .../data/notification/NotificationReceiver.kt | 5 +- .../tachiyomi/ui/anime/AnimeController.kt | 21 ++++- .../tachiyomi/ui/watcher/WatcherActivity.kt | 84 ++++++++++++++++++- app/src/main/res/layout/watcher_activity.xml | 22 ++++- ...rol_view.xml => watcher_controls_view.xml} | 21 +++-- app/src/main/res/values/strings.xml | 1 + 7 files changed, 134 insertions(+), 23 deletions(-) rename app/src/main/res/layout/{exo_player_control_view.xml => watcher_controls_view.xml} (86%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a99ee67fe..ad92d369e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -273,6 +273,9 @@ dependencies { implementation("com.google.android.exoplayer:exoplayer-dash:$exoplayerVersion") implementation("com.google.android.exoplayer:exoplayer-hls:$exoplayerVersion") implementation("com.google.android.exoplayer:exoplayer-ui:$exoplayerVersion") + + //player doubletap + implementation("com.github.vkay94:DoubleTapPlayerView:1.0.2") } tasks { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index fc9b0b7fa..4c4b77ea8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -24,6 +24,7 @@ import eu.kanade.tachiyomi.source.AnimeSourceManager import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.toEpisodeInfo import eu.kanade.tachiyomi.ui.anime.AnimeController +import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.reader.ReaderActivity @@ -39,6 +40,7 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy import java.io.File +import java.util.Collections.emptyList import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID @@ -453,7 +455,8 @@ class NotificationReceiver : BroadcastReceiver() { } } } - val newIntent = WatcherActivity.newIntent(context, anime, episode, link) + val episodeList: List = emptyList() + val newIntent = WatcherActivity.newIntent(context, anime, episode, episodeList, link) return PendingIntent.getActivity(context, anime.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/anime/AnimeController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/anime/AnimeController.kt index 4ef977083..d0ed8bb2d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/anime/AnimeController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/anime/AnimeController.kt @@ -81,7 +81,6 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import okhttp3.Callback import reactivecircus.flowbinding.recyclerview.scrollEvents import reactivecircus.flowbinding.swiperefreshlayout.refreshes import timber.log.Timber @@ -641,11 +640,24 @@ class AnimeController : } if (requestCode == REQUEST_SECONDS) { val seconds = data!!.getLongExtra("seconds_result", 0) - val total_seconds = data.getLongExtra("total_seconds_result", 0) + val totalSeconds = data.getLongExtra("total_seconds_result", 0) val episode: Episode = data.getSerializableExtra("episode") as Episode episode.last_second_seen = seconds - episode.total_seconds = total_seconds + episode.total_seconds = totalSeconds presenter.setEpisodesProgress(arrayListOf(EpisodeItem(episode, anime!!))) + // if next or previous episode was pressed + if (data.getBooleanExtra("nextResult", false)) { + val episodeList = presenter.episodes.sortedWith(presenter.getEpisodeSort()) + val idx = episodeList.indexOfFirst { it.episode_number == episode.episode_number } + val nextEpisode = episodeList[idx - 1].episode + openEpisode(nextEpisode) + } + if (data.getBooleanExtra("previousResult", false)) { + val episodeList = presenter.episodes.sortedWith(presenter.getEpisodeSort()) + val idx = episodeList.indexOfFirst { it.episode_number == episode.episode_number } + val previousEpisode = episodeList[idx + 1].episode + openEpisode(previousEpisode) + } } } @@ -744,7 +756,8 @@ class AnimeController : runBlocking { launch { val url = fetchEpisodeLinksFromSource(false, episode) - val intent = WatcherActivity.newIntent(activity, presenter.anime, episode, url) + val episodeList = presenter.episodes.sortedWith(presenter.getEpisodeSort()) + val intent = WatcherActivity.newIntent(activity, presenter.anime, episode, episodeList, url) if (hasAnimation) { intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/watcher/WatcherActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/watcher/WatcherActivity.kt index 668255e0b..83806b44d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/watcher/WatcherActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/watcher/WatcherActivity.kt @@ -3,11 +3,15 @@ package eu.kanade.tachiyomi.ui.watcher import android.content.Context import android.content.Intent import android.os.Bundle +import android.view.View +import android.widget.ImageButton +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import com.github.vkay94.dtpv.DoubleTapPlayerView +import com.github.vkay94.dtpv.youtube.YouTubeOverlay import com.google.android.exoplayer2.* import com.google.android.exoplayer2.source.TrackGroupArray import com.google.android.exoplayer2.trackselection.TrackSelectionArray -import com.google.android.exoplayer2.ui.PlayerView import com.google.android.exoplayer2.upstream.DataSource import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory import com.google.android.exoplayer2.util.MimeTypes @@ -15,6 +19,7 @@ import com.google.android.exoplayer2.util.Util import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Anime import eu.kanade.tachiyomi.data.database.models.Episode +import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem import eu.kanade.tachiyomi.util.view.hideBar const val STATE_RESUME_WINDOW = "resumeWindow" @@ -26,7 +31,11 @@ class WatcherActivity : AppCompatActivity() { private lateinit var exoPlayer: SimpleExoPlayer private lateinit var dataSourceFactory: DataSource.Factory - private lateinit var playerView: PlayerView + private lateinit var playerView: DoubleTapPlayerView + private lateinit var youTubeDoubleTap: YouTubeOverlay + private lateinit var skipBtn: TextView + private lateinit var nextBtn: ImageButton + private lateinit var prevBtn: ImageButton private var duration: Long = 0 private var currentWindow = 0 @@ -45,6 +54,23 @@ class WatcherActivity : AppCompatActivity() { window.hideBar() } playerView = findViewById(R.id.player_view) + youTubeDoubleTap = findViewById(R.id.youtube_overlay) + youTubeDoubleTap + .performListener(object : YouTubeOverlay.PerformListener { + override fun onAnimationStart() { + // Do UI changes when circle scaling animation starts (e.g. hide controller views) + youTubeDoubleTap.visibility = View.VISIBLE + } + + override fun onAnimationEnd() { + // Do UI changes when circle scaling animation starts (e.g. show controller views) + youTubeDoubleTap.visibility = View.GONE + } + }) + skipBtn = findViewById(R.id.watcher_controls_skip_btn) + nextBtn = findViewById(R.id.watcher_controls_next) + prevBtn = findViewById(R.id.watcher_controls_prev) + dataSourceFactory = DefaultDataSourceFactory(this, Util.getUserAgent(this, "xyz.jmir.tachiyomi.mi")) mediaItem = MediaItem.Builder() .setUri(intent.getStringExtra("uri")) @@ -81,6 +107,18 @@ class WatcherActivity : AppCompatActivity() { override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters) {} } exoPlayer.addListener(PlayerEventListener()) + skipBtn.setOnClickListener { exoPlayer.seekTo(exoPlayer.currentPosition + 85000) } + if (intent.getBooleanExtra("hasNextEpisode", false)) { + nextBtn.setOnClickListener { + nextEpisode() + } + } + if (intent.getBooleanExtra("hasPreviousEpisode", false)) { + prevBtn.setOnClickListener { + previousEpisode() + } + } + youTubeDoubleTap.player(exoPlayer) playerView.player = exoPlayer duration = exoPlayer.duration } @@ -91,6 +129,7 @@ class WatcherActivity : AppCompatActivity() { } private fun releasePlayer() { + youTubeDoubleTap.player(exoPlayer) isPlayerPlaying = exoPlayer.playWhenReady playbackPosition = exoPlayer.currentPosition currentWindow = exoPlayer.currentWindowIndex @@ -101,6 +140,38 @@ class WatcherActivity : AppCompatActivity() { returnIntent.putExtra("episode", episode) setResult(RESULT_OK, returnIntent) exoPlayer.release() + super.onBackPressed() + } + + private fun nextEpisode() { + youTubeDoubleTap.player(exoPlayer) + isPlayerPlaying = exoPlayer.playWhenReady + playbackPosition = exoPlayer.currentPosition + currentWindow = exoPlayer.currentWindowIndex + val episode = intent.getSerializableExtra("episode") as Episode + val returnIntent = intent + returnIntent.putExtra("seconds_result", playbackPosition) + returnIntent.putExtra("total_seconds_result", exoPlayer.duration) + returnIntent.putExtra("episode", episode) + returnIntent.putExtra("nextResult", true) + setResult(RESULT_OK, returnIntent) + exoPlayer.release() + super.onBackPressed() + } + + private fun previousEpisode() { + youTubeDoubleTap.player(exoPlayer) + isPlayerPlaying = exoPlayer.playWhenReady + playbackPosition = exoPlayer.currentPosition + currentWindow = exoPlayer.currentWindowIndex + val episode = intent.getSerializableExtra("episode") as Episode + val returnIntent = intent + returnIntent.putExtra("seconds_result", playbackPosition) + returnIntent.putExtra("total_seconds_result", exoPlayer.duration) + returnIntent.putExtra("episode", episode) + returnIntent.putExtra("previousResult", true) + setResult(RESULT_OK, returnIntent) + exoPlayer.release() } override fun onSaveInstanceState(outState: Bundle) { @@ -144,12 +215,19 @@ class WatcherActivity : AppCompatActivity() { } companion object { - fun newIntent(context: Context, anime: Anime, episode: Episode, url: String): Intent { + fun newIntent(context: Context, anime: Anime, episode: Episode, episodeList: List, url: String): Intent { return Intent(context, WatcherActivity::class.java).apply { putExtra("anime", anime.id) putExtra("episode", episode) putExtra("second", episode.last_second_seen) putExtra("uri", url) + if (episodeList.isNotEmpty()) { + putExtra("hasNextEpisode", episode.episode_number < episodeList[0].episode_number) + putExtra("hasPreviousEpisode", episode.episode_number > episodeList[episodeList.size - 1].episode_number) + } else { + putExtra("hasNextEpisode", false) + putExtra("hasPreviousEpisode", false) + } addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) } } diff --git a/app/src/main/res/layout/watcher_activity.xml b/app/src/main/res/layout/watcher_activity.xml index fdecd3a67..d9de762a3 100644 --- a/app/src/main/res/layout/watcher_activity.xml +++ b/app/src/main/res/layout/watcher_activity.xml @@ -5,19 +5,33 @@ android:layout_height="match_parent" android:orientation="vertical"> - - + app:controller_layout_id="@layout/watcher_controls_view" + app:fastforward_increment="85000" + app:dtpv_controller="@+id/youtube_overlay" + app:show_buffering="when_playing"/> + + - \ No newline at end of file + + + + diff --git a/app/src/main/res/layout/exo_player_control_view.xml b/app/src/main/res/layout/watcher_controls_view.xml similarity index 86% rename from app/src/main/res/layout/exo_player_control_view.xml rename to app/src/main/res/layout/watcher_controls_view.xml index 2759f6ff1..705307b7c 100644 --- a/app/src/main/res/layout/exo_player_control_view.xml +++ b/app/src/main/res/layout/watcher_controls_view.xml @@ -25,27 +25,26 @@ android:paddingTop="4dp" android:orientation="horizontal"> - - - - - - - - + + Previous page Next page + +85 s