mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-09-26 11:19:05 +00:00
Fixes to connectivity loss playback restart and fixes to added ensureEnoughContentVisible.
This commit is contained in:
parent
fc5888d57e
commit
23d1085755
3 changed files with 43 additions and 25 deletions
|
@ -390,7 +390,7 @@ class Settings : FragmentedStorageFileJson() {
|
||||||
@DropdownFieldOptionsId(R.array.restart_playback_after_loss)
|
@DropdownFieldOptionsId(R.array.restart_playback_after_loss)
|
||||||
var restartPlaybackAfterLoss: Int = 1;
|
var restartPlaybackAfterLoss: Int = 1;
|
||||||
|
|
||||||
@FormField(R.string.restart_after_connectivity_loss, FieldForm.DROPDOWN, R.string.restart_playback_when_gaining_connectivity_after_a_loss, 11)
|
@FormField(R.string.restart_after_connectivity_loss, FieldForm.DROPDOWN, R.string.restart_playback_when_gaining_connectivity_after_a_loss, 12)
|
||||||
@DropdownFieldOptionsId(R.array.restart_playback_after_loss)
|
@DropdownFieldOptionsId(R.array.restart_playback_after_loss)
|
||||||
var restartPlaybackAfterConnectivityLoss: Int = 1;
|
var restartPlaybackAfterConnectivityLoss: Int = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
import com.futo.platformplayer.*
|
import com.futo.platformplayer.*
|
||||||
import com.futo.platformplayer.api.media.IPlatformClient
|
import com.futo.platformplayer.api.media.IPlatformClient
|
||||||
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSPager
|
import com.futo.platformplayer.api.media.platforms.js.models.JSPager
|
||||||
import com.futo.platformplayer.api.media.structures.*
|
import com.futo.platformplayer.api.media.structures.*
|
||||||
import com.futo.platformplayer.constructs.Event1
|
import com.futo.platformplayer.constructs.Event1
|
||||||
|
@ -21,7 +20,6 @@ import com.futo.platformplayer.constructs.TaskHandler
|
||||||
import com.futo.platformplayer.engine.exceptions.PluginException
|
import com.futo.platformplayer.engine.exceptions.PluginException
|
||||||
import com.futo.platformplayer.logging.Logger
|
import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.views.FeedStyle
|
import com.futo.platformplayer.views.FeedStyle
|
||||||
import com.futo.platformplayer.views.adapters.ContentPreviewViewHolder
|
|
||||||
import com.futo.platformplayer.views.others.ProgressBar
|
import com.futo.platformplayer.views.others.ProgressBar
|
||||||
import com.futo.platformplayer.views.others.TagsView
|
import com.futo.platformplayer.views.others.TagsView
|
||||||
import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
|
import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
|
||||||
|
@ -64,6 +62,7 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
||||||
val fragment: TFragment;
|
val fragment: TFragment;
|
||||||
|
|
||||||
private val _scrollListener: RecyclerView.OnScrollListener;
|
private val _scrollListener: RecyclerView.OnScrollListener;
|
||||||
|
private var _automaticNextPageCounter = 0;
|
||||||
|
|
||||||
constructor(fragment: TFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData<InsertedViewAdapterWithLoader<TViewHolder>, LinearLayoutManager, TPager, TResult, TConverted, InsertedViewHolder<TViewHolder>>? = null) : super(inflater.context) {
|
constructor(fragment: TFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData<InsertedViewAdapterWithLoader<TViewHolder>, LinearLayoutManager, TPager, TResult, TConverted, InsertedViewHolder<TViewHolder>>? = null) : super(inflater.context) {
|
||||||
this.fragment = fragment;
|
this.fragment = fragment;
|
||||||
|
@ -122,7 +121,6 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
||||||
|
|
||||||
_toolbarContentView = findViewById(R.id.container_toolbar_content);
|
_toolbarContentView = findViewById(R.id.container_toolbar_content);
|
||||||
|
|
||||||
var filteredNextPageCounter = 0;
|
|
||||||
_nextPageHandler = TaskHandler<TPager, List<TResult>>({fragment.lifecycleScope}, {
|
_nextPageHandler = TaskHandler<TPager, List<TResult>>({fragment.lifecycleScope}, {
|
||||||
if (it is IAsyncPager<*>)
|
if (it is IAsyncPager<*>)
|
||||||
it.nextPageAsync();
|
it.nextPageAsync();
|
||||||
|
@ -142,15 +140,8 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
||||||
val filteredResults = filterResults(it);
|
val filteredResults = filterResults(it);
|
||||||
recyclerData.results.addAll(filteredResults);
|
recyclerData.results.addAll(filteredResults);
|
||||||
recyclerData.resultsUnfiltered.addAll(it);
|
recyclerData.resultsUnfiltered.addAll(it);
|
||||||
if(filteredResults.isEmpty()) {
|
|
||||||
filteredNextPageCounter++
|
|
||||||
if(filteredNextPageCounter <= 4)
|
|
||||||
loadNextPage()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filteredNextPageCounter = 0;
|
|
||||||
recyclerData.adapter.notifyItemRangeInserted(recyclerData.adapter.childToParentPosition(posBefore), filteredResults.size);
|
recyclerData.adapter.notifyItemRangeInserted(recyclerData.adapter.childToParentPosition(posBefore), filteredResults.size);
|
||||||
}
|
ensureEnoughContentVisible(filteredResults)
|
||||||
}.exception<Throwable> {
|
}.exception<Throwable> {
|
||||||
Logger.w(TAG, "Failed to load next page.", it);
|
Logger.w(TAG, "Failed to load next page.", it);
|
||||||
UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_next_page), it, {
|
UIDialogs.showGeneralRetryErrorDialog(context, context.getString(R.string.failed_to_load_next_page), it, {
|
||||||
|
@ -170,8 +161,10 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
||||||
|
|
||||||
val visibleItemCount = _recyclerResults.childCount;
|
val visibleItemCount = _recyclerResults.childCount;
|
||||||
val firstVisibleItem = recyclerData.layoutManager.findFirstVisibleItemPosition();
|
val firstVisibleItem = recyclerData.layoutManager.findFirstVisibleItemPosition();
|
||||||
|
//Logger.i(TAG, "onScrolled loadNextPage visibleItemCount=$visibleItemCount firstVisibleItem=$visibleItemCount")
|
||||||
|
|
||||||
if (!_loading && firstVisibleItem + visibleItemCount + visibleThreshold >= recyclerData.results.size && firstVisibleItem > 0) {
|
if (!_loading && firstVisibleItem + visibleItemCount + visibleThreshold >= recyclerData.results.size && firstVisibleItem > 0) {
|
||||||
//Logger.i(TAG, "loadNextPage(): firstVisibleItem=$firstVisibleItem visibleItemCount=$visibleItemCount visibleThreshold=$visibleThreshold _results.size=${_results.size}")
|
//Logger.i(TAG, "onScrolled loadNextPage(): firstVisibleItem=$firstVisibleItem visibleItemCount=$visibleItemCount visibleThreshold=$visibleThreshold recyclerData.results.size=${recyclerData.results.size}")
|
||||||
loadNextPage();
|
loadNextPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +173,33 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
||||||
_recyclerResults.addOnScrollListener(_scrollListener);
|
_recyclerResults.addOnScrollListener(_scrollListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ensureEnoughContentVisible(filteredResults: List<TConverted>) {
|
||||||
|
val canScroll = if (recyclerData.results.isEmpty()) false else {
|
||||||
|
val layoutManager = recyclerData.layoutManager
|
||||||
|
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
|
||||||
|
|
||||||
|
if (firstVisibleItemPosition != RecyclerView.NO_POSITION) {
|
||||||
|
val firstVisibleView = layoutManager.findViewByPosition(firstVisibleItemPosition)
|
||||||
|
val itemHeight = firstVisibleView?.height ?: 0
|
||||||
|
val occupiedSpace = recyclerData.results.size * itemHeight
|
||||||
|
val recyclerViewHeight = _recyclerResults.height
|
||||||
|
Logger.i(TAG, "ensureEnoughContentVisible loadNextPage occupiedSpace=$occupiedSpace recyclerViewHeight=$recyclerViewHeight")
|
||||||
|
occupiedSpace >= recyclerViewHeight
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Logger.i(TAG, "ensureEnoughContentVisible loadNextPage canScroll=$canScroll _automaticNextPageCounter=$_automaticNextPageCounter")
|
||||||
|
if (!canScroll || filteredResults.isEmpty()) {
|
||||||
|
_automaticNextPageCounter++
|
||||||
|
if(_automaticNextPageCounter <= 4)
|
||||||
|
loadNextPage()
|
||||||
|
} else {
|
||||||
|
_automaticNextPageCounter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected fun setTextCentered(text: String?) {
|
protected fun setTextCentered(text: String?) {
|
||||||
_textCentered.text = text;
|
_textCentered.text = text;
|
||||||
}
|
}
|
||||||
|
@ -369,6 +389,7 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
||||||
recyclerData.resultsUnfiltered.addAll(toAdd);
|
recyclerData.resultsUnfiltered.addAll(toAdd);
|
||||||
recyclerData.adapter.notifyDataSetChanged();
|
recyclerData.adapter.notifyDataSetChanged();
|
||||||
recyclerData.loadedFeedStyle = feedStyle;
|
recyclerData.loadedFeedStyle = feedStyle;
|
||||||
|
ensureEnoughContentVisible(filteredResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun detachPagerEvents() {
|
private fun detachPagerEvents() {
|
||||||
|
|
|
@ -156,22 +156,21 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
val dur = duration;
|
val dur = duration;
|
||||||
var shouldRestartPlayback = false
|
var shouldRestartPlayback = false
|
||||||
if (_shouldPlaybackRestartOnConnectivity && abs(pos - dur) > 2000) {
|
if (_shouldPlaybackRestartOnConnectivity && abs(pos - dur) > 2000) {
|
||||||
if (Settings.instance.playback.restartPlaybackAfterLoss == 1) {
|
if (Settings.instance.playback.restartPlaybackAfterConnectivityLoss == 1) {
|
||||||
val lossTime_ms = _connectivityLossTime_ms
|
val lossTime_ms = _connectivityLossTime_ms
|
||||||
if (lossTime_ms != null && System.currentTimeMillis() - lossTime_ms < 1000 * 30) {
|
if (lossTime_ms != null && System.currentTimeMillis() - lossTime_ms < 1000 * 30) {
|
||||||
shouldRestartPlayback = true
|
shouldRestartPlayback = true
|
||||||
}
|
}
|
||||||
} else if (Settings.instance.playback.restartPlaybackAfterLoss == 2) {
|
} else if (Settings.instance.playback.restartPlaybackAfterConnectivityLoss == 2) {
|
||||||
val lossTime_ms = _connectivityLossTime_ms
|
val lossTime_ms = _connectivityLossTime_ms
|
||||||
if (lossTime_ms != null && System.currentTimeMillis() - lossTime_ms < 1000 * 10) {
|
if (lossTime_ms != null && System.currentTimeMillis() - lossTime_ms < 1000 * 10) {
|
||||||
shouldRestartPlayback = true
|
shouldRestartPlayback = true
|
||||||
}
|
}
|
||||||
} else if (Settings.instance.playback.restartPlaybackAfterLoss == 3) {
|
} else if (Settings.instance.playback.restartPlaybackAfterConnectivityLoss == 3) {
|
||||||
shouldRestartPlayback = true
|
shouldRestartPlayback = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (shouldRestartPlayback) {
|
if (shouldRestartPlayback) {
|
||||||
Logger.i(TAG, "Playback ended due to connection loss, resuming playback since connection is restored.");
|
Logger.i(TAG, "Playback ended due to connection loss, resuming playback since connection is restored.");
|
||||||
exoPlayer?.player?.playWhenReady = true;
|
exoPlayer?.player?.playWhenReady = true;
|
||||||
|
@ -529,13 +528,13 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS -> {
|
PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS -> {
|
||||||
onDatasourceError.emit(error);
|
onDatasourceError.emit(error);
|
||||||
}
|
}
|
||||||
PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED,
|
//PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED,
|
||||||
PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND,
|
//PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND,
|
||||||
PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE,
|
//PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE,
|
||||||
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
|
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
|
||||||
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT,
|
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT,
|
||||||
PlaybackException.ERROR_CODE_IO_NO_PERMISSION,
|
//PlaybackException.ERROR_CODE_IO_NO_PERMISSION,
|
||||||
PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE,
|
//PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE,
|
||||||
PlaybackException.ERROR_CODE_IO_UNSPECIFIED -> {
|
PlaybackException.ERROR_CODE_IO_UNSPECIFIED -> {
|
||||||
Logger.i(TAG, "IO error, set _shouldPlaybackRestartOnConnectivity=true");
|
Logger.i(TAG, "IO error, set _shouldPlaybackRestartOnConnectivity=true");
|
||||||
_shouldPlaybackRestartOnConnectivity = true;
|
_shouldPlaybackRestartOnConnectivity = true;
|
||||||
|
@ -557,8 +556,6 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
Logger.i(TAG, "_shouldPlaybackRestartOnConnectivity=false");
|
Logger.i(TAG, "_shouldPlaybackRestartOnConnectivity=false");
|
||||||
_shouldPlaybackRestartOnConnectivity = false;
|
_shouldPlaybackRestartOnConnectivity = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue