diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 38310f5..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,35 +0,0 @@ -# Change Log - -## 2.1.0 - -- improves seeking workaround -- split up conferences and events -- dedicated event list section - -## 2.0.0 - -- adds streaming -- adds Room for caching Events - -## 1.2.0 - -### Added - -- adds search, uses new media.ccc.de API for search - -### Fixed - -- Fixes Bug with initially wrong used Aspect Ratios - -## 1.1.0 - -### Added - -- Adds Aspect Ratio Button to playback -- Adds Video Quality Button to playback -- Prioritize MP4 over Webm -- Adds App Banner for Dev Version - -## 1.0.0 - -- Initial Version \ No newline at end of file diff --git a/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailContract.kt b/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailContract.kt index f7f4e25..632d11a 100644 --- a/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailContract.kt +++ b/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailContract.kt @@ -7,7 +7,7 @@ import io.reactivex.Single internal interface Inputs { fun toggleBookmark() - fun savePlaybackPosition(seconds: Int) + fun savePlaybackPosition(playedSeconds: Int, totalDurationSeconds: Int) } internal interface Outputs { diff --git a/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailFragment.kt b/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailFragment.kt index 68e2b37..3df1ed6 100644 --- a/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailFragment.kt +++ b/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailFragment.kt @@ -75,8 +75,13 @@ class DetailFragment : DetailsSupportFragment() { override fun onPause() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || activity?.isInPictureInPictureMode == false) { - playerAdapter?.currentPosition?.let { currentMillis -> - viewModel.inputs.savePlaybackPosition((currentMillis / 1000).toInt()) + val currentMillis = playerAdapter?.currentPosition + val durationMillis = playerAdapter?.duration + if(currentMillis != null && durationMillis != null) { + viewModel.inputs.savePlaybackPosition( + playedSeconds = (currentMillis / 1000).toInt(), + totalDurationSeconds = (durationMillis /1000).toInt() + ) } detailsBackground.playbackGlue?.pause() } diff --git a/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailViewModel.kt b/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailViewModel.kt index 2fff482..b65d8e3 100644 --- a/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailViewModel.kt +++ b/app/src/main/java/de/stefanmedack/ccctv/ui/detail/DetailViewModel.kt @@ -25,8 +25,6 @@ class DetailViewModel @Inject constructor( internal val inputs: Inputs = this internal val outputs: Outputs = this - private val SAVE_PLAYBACK_SECONDS_THRESHOLD = 60 - private var eventId: Int = -1 fun init(eventId: Int) { @@ -44,8 +42,8 @@ class DetailViewModel @Inject constructor( bookmarkClickStream.onNext(0) } - override fun savePlaybackPosition(seconds: Int) { - savePlayPositionStream.onNext(seconds) + override fun savePlaybackPosition(playedSeconds: Int, totalDurationSeconds: Int) { + savePlayPositionStream.onNext(PlaybackData(playedSeconds, totalDurationSeconds)) } // @@ -70,7 +68,7 @@ class DetailViewModel @Inject constructor( // private val bookmarkClickStream = PublishSubject.create() - private val savePlayPositionStream = PublishSubject.create() + private val savePlayPositionStream = PublishSubject.create() private val doToggleBookmark get() = bookmarkClickStream @@ -80,8 +78,8 @@ class DetailViewModel @Inject constructor( private val doSavePlayedSeconds get() = savePlayPositionStream .flatMapCompletable { - if (it > SAVE_PLAYBACK_SECONDS_THRESHOLD) { - repository.savePlayedSeconds(eventId, it) + if (it.hasPlayedMinimumToSave() && !it.hasAlmostFinished()) { + repository.savePlayedSeconds(eventId, it.playedSeconds) } else { repository.deletePlayedSeconds(eventId) } @@ -100,4 +98,20 @@ class DetailViewModel @Inject constructor( private fun updateBookmarkState(isBookmarked: Boolean): Completable = repository.changeBookmarkState(eventId, !isBookmarked) + private data class PlaybackData( + val playedSeconds: Int, + val totalDurationSeconds: Int + ) { + + private val MINIMUM_PLAYBACK_SECONDS_TO_SAVE = 60 + private val MAXIMUM_PLAYBACK_PERCENT_TO_SAVE = .9f + + fun hasPlayedMinimumToSave(): Boolean = this.playedSeconds > MINIMUM_PLAYBACK_SECONDS_TO_SAVE + + fun hasAlmostFinished(): Boolean = when { + totalDurationSeconds > 0 -> (playedSeconds.toFloat() / totalDurationSeconds.toFloat()) > MAXIMUM_PLAYBACK_PERCENT_TO_SAVE + else -> true + } + } + } \ No newline at end of file diff --git a/app/src/test/java/de/stefanmedack/ccctv/ui/detail/DetailViewModelTest.kt b/app/src/test/java/de/stefanmedack/ccctv/ui/detail/DetailViewModelTest.kt index faa7a00..89da8c9 100644 --- a/app/src/test/java/de/stefanmedack/ccctv/ui/detail/DetailViewModelTest.kt +++ b/app/src/test/java/de/stefanmedack/ccctv/ui/detail/DetailViewModelTest.kt @@ -80,7 +80,7 @@ class DetailViewModelTest { val testEventId = 3 detailViewModel.init(testEventId) - detailViewModel.inputs.savePlaybackPosition(seconds = 180) + detailViewModel.inputs.savePlaybackPosition(playedSeconds = 180, totalDurationSeconds = 2300) verify(repository).savePlayedSeconds(eventId = testEventId, seconds = 180) } @@ -90,7 +90,17 @@ class DetailViewModelTest { val testEventId = 3 detailViewModel.init(testEventId) - detailViewModel.inputs.savePlaybackPosition(seconds = 30) + detailViewModel.inputs.savePlaybackPosition(playedSeconds = 30, totalDurationSeconds = 2300) + + verify(repository).deletePlayedSeconds(3) + } + + @Test + fun `saving playback position when video is almost finished should delete saved playback position`() { + val testEventId = 3 + detailViewModel.init(testEventId) + + detailViewModel.inputs.savePlaybackPosition(playedSeconds = 2250, totalDurationSeconds = 2300) verify(repository).deletePlayedSeconds(3) }