diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 05675554..9b88b00b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -51,7 +51,6 @@
android:name=".activities.MainActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true"
- android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar"
android:launchMode="singleTask"
android:resizeableActivity="true"
@@ -153,27 +152,21 @@
@@ -187,44 +180,34 @@
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/platformplayer/Settings.kt b/app/src/main/java/com/futo/platformplayer/Settings.kt
index ffb6e3a5..049f570e 100644
--- a/app/src/main/java/com/futo/platformplayer/Settings.kt
+++ b/app/src/main/java/com/futo/platformplayer/Settings.kt
@@ -2,11 +2,8 @@ package com.futo.platformplayer
import android.content.ActivityNotFoundException
import android.content.Context
-import android.content.Context.POWER_SERVICE
import android.content.Intent
import android.net.Uri
-import android.os.Build
-import android.os.PowerManager
import android.webkit.CookieManager
import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.activities.MainActivity
@@ -26,7 +23,6 @@ import com.futo.platformplayer.states.StateBackup
import com.futo.platformplayer.states.StateCache
import com.futo.platformplayer.states.StateMeta
import com.futo.platformplayer.states.StatePayment
-import com.futo.platformplayer.states.StatePlayer
import com.futo.platformplayer.states.StatePolycentric
import com.futo.platformplayer.states.StateUpdate
import com.futo.platformplayer.stores.FragmentedStorage
@@ -36,9 +32,7 @@ import com.futo.platformplayer.views.fields.DropdownFieldOptionsId
import com.futo.platformplayer.views.fields.FieldForm
import com.futo.platformplayer.views.fields.FormField
import com.futo.platformplayer.views.fields.FormFieldButton
-import com.futo.platformplayer.views.fields.FormFieldWarning
import com.futo.platformplayer.views.overlays.slideup.SlideUpMenuItem
-import com.stripe.android.customersheet.injection.CustomerSheetViewModelModule_Companion_ContextFactory.context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -417,8 +411,6 @@ class Settings : FragmentedStorageFileJson() {
@DropdownFieldOptionsId(R.array.system_enabled_disabled_array)
var autoRotate: Int = 2;
- fun isAutoRotate() = (autoRotate == 1 && !StatePlayer.instance.rotationLock) || (autoRotate == 2 && StateApp.instance.getCurrentSystemAutoRotate() && !StatePlayer.instance.rotationLock);
-
@FormField(R.string.background_behavior, FieldForm.DROPDOWN, -1, 7)
@DropdownFieldOptionsId(R.array.player_background_behavior)
var backgroundPlay: Int = 2;
@@ -857,10 +849,6 @@ class Settings : FragmentedStorageFileJson() {
var other = Other();
@Serializable
class Other {
- @FormField(R.string.bypass_rotation_prevention, FieldForm.TOGGLE, R.string.bypass_rotation_prevention_description, 1)
- @FormFieldWarning(R.string.bypass_rotation_prevention_warning)
- var bypassRotationPrevention: Boolean = false;
-
@FormField(R.string.enable_polycentric, FieldForm.TOGGLE, R.string.can_be_disabled_when_you_are_experiencing_issues, 1)
var polycentricEnabled: Boolean = true;
}
diff --git a/app/src/main/java/com/futo/platformplayer/SimpleOrientationListener.kt b/app/src/main/java/com/futo/platformplayer/SimpleOrientationListener.kt
deleted file mode 100644
index a289f02b..00000000
--- a/app/src/main/java/com/futo/platformplayer/SimpleOrientationListener.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.futo.platformplayer
-
-import android.app.Activity
-import android.content.pm.ActivityInfo
-import android.hardware.SensorManager
-import android.view.OrientationEventListener
-import com.futo.platformplayer.constructs.Event1
-import com.futo.platformplayer.logging.Logger
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-
-class SimpleOrientationListener(
- private val activity: Activity,
- private val lifecycleScope: CoroutineScope
-) {
- private var lastOrientation: Int = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- private var lastStableOrientation: Int = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- private val stabilityThresholdTime = 500L
-
- val onOrientationChanged = Event1()
-
- private val orientationListener = object : OrientationEventListener(activity, SensorManager.SENSOR_DELAY_UI) {
- override fun onOrientationChanged(orientation: Int) {
- //val rotationZone = 45
- val rotationZone = when (Settings.instance.playback.rotationZone) {
- 0 -> 15
- 1 -> 30
- 2 -> 45
- else -> 45
- }
-
- val newOrientation = when {
- orientation in (90 - rotationZone)..(90 + rotationZone - 1) -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
- orientation in (180 - rotationZone)..(180 + rotationZone - 1) -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
- orientation in (270 - rotationZone)..(270 + rotationZone - 1) -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
- orientation in (360 - rotationZone)..(360 + rotationZone - 1) || orientation in 0..(rotationZone - 1) -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
- else -> lastOrientation
- }
-
- if (newOrientation != lastStableOrientation) {
- lastStableOrientation = newOrientation
-
- lifecycleScope.launch(Dispatchers.Main) {
- try {
- delay(stabilityThresholdTime)
- if (newOrientation == lastStableOrientation) {
- lastOrientation = newOrientation
- onOrientationChanged.emit(newOrientation)
- }
- } catch (e: Throwable) {
- Logger.i(TAG, "Failed to trigger onOrientationChanged", e)
- }
- }
- }
- }
- }
-
- init {
- orientationListener.enable()
- lastOrientation = activity.resources.configuration.orientation
- }
-
- fun stopListening() {
- orientationListener.disable()
- }
-
- companion object {
- private val TAG = "SimpleOrientationListener"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt
index bd998d38..f9aee81a 100644
--- a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt
+++ b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt
@@ -7,7 +7,6 @@ import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.net.Uri
-import android.net.wifi.WifiManager
import android.os.Bundle
import android.os.StrictMode
import android.os.StrictMode.VmPolicy
@@ -515,6 +514,9 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
sharedPreferences.edit().putBoolean("IsFirstBoot", false).apply()
}
+
+ _fragVideoDetail.detectWindowSize()
+ _fragVideoDetail.updateOrientation()
}
/*
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/bottombar/MenuBottomBarFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/bottombar/MenuBottomBarFragment.kt
index d3003991..56b3de79 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/bottombar/MenuBottomBarFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/bottombar/MenuBottomBarFragment.kt
@@ -7,6 +7,7 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
+import android.content.res.Configuration
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -34,7 +35,7 @@ import kotlin.math.roundToInt
class MenuBottomBarFragment : MainActivityFragment() {
private var _view: MenuBottomBarView? = null;
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = MenuBottomBarView(this, inflater);
_view = view;
return view;
@@ -56,7 +57,13 @@ class MenuBottomBarFragment : MainActivityFragment() {
return _view?.onBackPressed() ?: false;
}
- @SuppressLint("ViewConstructor")
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+
+ _view?.updateAllButtonVisibility()
+ }
+
+ @SuppressLint("ViewConstructor")
class MenuBottomBarView : LinearLayout {
private val _fragment: MenuBottomBarFragment;
private val _inflater: LayoutInflater;
@@ -76,7 +83,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
private var _buttonsVisible = 0;
private var _subscriptionsVisible = true;
- var currentButtonDefinitions: List? = null;
+ private var currentButtonDefinitions: List? = null;
constructor(fragment: MenuBottomBarFragment, inflater: LayoutInflater) : super(inflater.context) {
_fragment = fragment;
@@ -132,7 +139,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
val staggerFactor = 3.0f
if (visible) {
- moreOverlay.visibility = LinearLayout.VISIBLE
+ moreOverlay.visibility = VISIBLE
val animations = arrayListOf()
animations.add(ObjectAnimator.ofFloat(moreOverlayBackground, "alpha", 0.0f, 1.0f).setDuration(duration))
@@ -161,7 +168,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
animatorSet.doOnEnd {
_moreVisibleAnimating = false
_moreVisible = false
- moreOverlay.visibility = LinearLayout.INVISIBLE
+ moreOverlay.visibility = INVISIBLE
}
animatorSet.playTogether(animations)
animatorSet.start()
@@ -178,7 +185,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
_layoutBottomBarButtons.removeAllViews();
_layoutBottomBarButtons.addView(Space(context).apply {
- layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
+ layoutParams = LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f)
})
for ((index, button) in buttons.withIndex()) {
@@ -192,7 +199,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
_layoutBottomBarButtons.addView(menuButton)
if (index < buttonDefinitions.size - 1) {
_layoutBottomBarButtons.addView(Space(context).apply {
- layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
+ layoutParams = LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f)
})
}
@@ -200,7 +207,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
}
_layoutBottomBarButtons.addView(Space(context).apply {
- layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
+ layoutParams = LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f)
})
}
@@ -251,9 +258,19 @@ class MenuBottomBarFragment : MainActivityFragment() {
button.updateActive(_fragment);
}
+ override fun onConfigurationChanged(newConfig: Configuration?) {
+ super.onConfigurationChanged(newConfig)
+
+ updateAllButtonVisibility()
+ }
+
fun updateAllButtonVisibility() {
+ if(_moreVisible) {
+ setMoreVisible(false)
+ }
+
val defs = currentButtonDefinitions?.toMutableList() ?: return
- val metrics = StateApp.instance.displayMetrics ?: resources.displayMetrics;
+ val metrics = resources.displayMetrics
_buttonsVisible = floor(metrics.widthPixels.toDouble() / 65.dp(resources).toDouble()).roundToInt();
if (_buttonsVisible >= defs.size) {
updateBottomMenuButtons(defs.toMutableList(), false);
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt
index 1a4537f6..17130779 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/ContentFeedView.kt
@@ -4,8 +4,8 @@ import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.widget.LinearLayout
-import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
import com.futo.platformplayer.UIDialogs
@@ -45,9 +45,7 @@ abstract class ContentFeedView : FeedView, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData) {
-
- }
+ constructor(fragment: TFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, StaggeredGridLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData)
override fun filterResults(results: List): List {
return results;
@@ -55,12 +53,12 @@ abstract class ContentFeedView : FeedView): InsertedViewAdapterWithLoader {
val player = StatePlayer.instance.getThumbnailPlayerOrCreate(context);
- player.modifyState("ThumbnailPlayer", { state -> state.muted = true });
+ player.modifyState("ThumbnailPlayer") { state -> state.muted = true };
_exoPlayer = player;
val v = LinearLayout(context).apply {
- layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
- orientation = LinearLayout.VERTICAL;
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ orientation = VERTICAL;
};
headerView = v;
@@ -142,7 +140,10 @@ abstract class ContentFeedView : FeedView()
.filter { it != content };
- StatePlayer.instance.setQueue(newQueue, StatePlayer.TYPE_QUEUE, "Feed Queue", true, false);
+ StatePlayer.instance.setQueue(newQueue, StatePlayer.TYPE_QUEUE, "Feed Queue",
+ focus = true,
+ shuffle = false
+ );
})
);
}
@@ -160,21 +161,27 @@ abstract class ContentFeedView : FeedView, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>) {
+ override fun onRestoreCachedData(cachedData: RecyclerData, StaggeredGridLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>) {
super.onRestoreCachedData(cachedData)
val v = LinearLayout(context).apply {
- layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
- orientation = LinearLayout.VERTICAL;
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ orientation = VERTICAL;
};
headerView = v;
cachedData.adapter.viewsToPrepend.add(v);
(cachedData.adapter as PreviewContentListAdapter?)?.let { attachAdapterEvents(it) };
}
- override fun createLayoutManager(recyclerResults: RecyclerView, context: Context): LinearLayoutManager {
- val llmResults = LinearLayoutManager(context);
- llmResults.orientation = LinearLayoutManager.VERTICAL;
- return llmResults;
+ override fun createLayoutManager(
+ recyclerResults: RecyclerView,
+ context: Context
+ ): StaggeredGridLayoutManager {
+ val glmResults =
+ StaggeredGridLayoutManager(
+ if (resources.configuration.screenWidthDp >= resources.getDimension(R.dimen.landscape_threshold)) 2 else 1,
+ StaggeredGridLayoutManager.VERTICAL
+ );
+ return glmResults
}
override fun onScrollStateChanged(newState: Int) {
@@ -220,8 +227,8 @@ abstract class ContentFeedView : FeedView : FeedView : FeedView : FeedView, CreatorViewHolder> where TFragment : MainFragment {
override val feedStyle: FeedStyle = FeedStyle.THUMBNAIL; //R.layout.list_creator;
- constructor(fragment: TFragment, inflater: LayoutInflater) : super(fragment, inflater) {
-
- }
+ constructor(fragment: TFragment, inflater: LayoutInflater) : super(fragment, inflater)
override fun createAdapter(recyclerResults: RecyclerView, context: Context, dataset: ArrayList): InsertedViewAdapterWithLoader {
return InsertedViewAdapterWithLoader(context, arrayListOf(), arrayListOf(),
@@ -34,18 +28,24 @@ abstract class CreatorFeedView : FeedView : L
protected val _recyclerResults: RecyclerView;
protected val _overlayContainer: FrameLayout;
protected val _swipeRefresh: SwipeRefreshLayout;
- private val _progress_bar: ProgressBar;
+ private val _progressBar: ProgressBar;
private val _spinnerSortBy: Spinner;
private val _containerSortBy: LinearLayout;
private val _tagsView: TagsView;
@@ -44,7 +45,7 @@ abstract class FeedView : L
private var _loading: Boolean = true;
- private val _pager_lock = Object();
+ private val _pagerLock = Object();
private var _cache: ItemCache? = null;
open val visibleThreshold = 15;
@@ -58,21 +59,21 @@ abstract class FeedView : L
private var _activeTags: List? = null;
private var _nextPageHandler: TaskHandler>;
- val recyclerData: RecyclerData, LinearLayoutManager, TPager, TResult, TConverted, InsertedViewHolder>;
+ val recyclerData: RecyclerData, StaggeredGridLayoutManager, TPager, TResult, TConverted, InsertedViewHolder>;
val fragment: TFragment;
private val _scrollListener: RecyclerView.OnScrollListener;
private var _automaticNextPageCounter = 0;
- constructor(fragment: TFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, LinearLayoutManager, TPager, TResult, TConverted, InsertedViewHolder>? = null) : super(inflater.context) {
+ constructor(fragment: TFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, StaggeredGridLayoutManager, TPager, TResult, TConverted, InsertedViewHolder>? = null) : super(inflater.context) {
this.fragment = fragment;
inflater.inflate(R.layout.fragment_feed, this);
_textCentered = findViewById(R.id.text_centered);
_emptyPagerContainer = findViewById(R.id.empty_pager_container);
- _progress_bar = findViewById(R.id.progress_bar);
- _progress_bar.inactiveColor = Color.TRANSPARENT;
+ _progressBar = findViewById(R.id.progress_bar);
+ _progressBar.inactiveColor = Color.TRANSPARENT;
_swipeRefresh = findViewById(R.id.swipe_refresh);
val recyclerResults: RecyclerView = findViewById(R.id.list_results);
@@ -158,7 +159,7 @@ abstract class FeedView : L
super.onScrolled(recyclerView, dx, dy);
val visibleItemCount = _recyclerResults.childCount;
- val firstVisibleItem = recyclerData.layoutManager.findFirstVisibleItemPosition();
+ val firstVisibleItem = recyclerData.layoutManager.findFirstVisibleItemPositions(IntArray(recyclerData.layoutManager.spanCount))[0]
//Logger.i(TAG, "onScrolled loadNextPage visibleItemCount=$visibleItemCount firstVisibleItem=$visibleItemCount")
if (!_loading && firstVisibleItem + visibleItemCount + visibleThreshold >= recyclerData.results.size && firstVisibleItem > 0) {
@@ -174,7 +175,7 @@ abstract class FeedView : L
private fun ensureEnoughContentVisible(filteredResults: List) {
val canScroll = if (recyclerData.results.isEmpty()) false else {
val layoutManager = recyclerData.layoutManager
- val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
+ val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPositions(IntArray(recyclerData.layoutManager.spanCount))[0]
if (firstVisibleItemPosition != RecyclerView.NO_POSITION) {
val firstVisibleView = layoutManager.findViewByPosition(firstVisibleItemPosition)
@@ -226,7 +227,23 @@ abstract class FeedView : L
}
}
+ private fun updateSpanCount() {
+ if (resources.configuration.screenWidthDp >= resources.getDimension(R.dimen.landscape_threshold) && recyclerData.layoutManager.spanCount != 2) {
+ recyclerData.layoutManager.spanCount = 2
+ } else if (resources.configuration.screenWidthDp < resources.getDimension(R.dimen.landscape_threshold) && recyclerData.layoutManager.spanCount != 1) {
+ recyclerData.layoutManager.spanCount = 1
+ }
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration?) {
+ super.onConfigurationChanged(newConfig)
+
+ updateSpanCount()
+ }
+
fun onResume() {
+ updateSpanCount()
+
//Reload the pager if the plugin was killed
val pager = recyclerData.pager;
if((pager is MultiPager<*> && pager.findPager { it is JSPager<*> && !it.isAvailable } != null) ||
@@ -252,7 +269,7 @@ abstract class FeedView : L
protected open fun setActiveTags(activeTags: List?) {
_activeTags = activeTags;
- if (activeTags != null && activeTags.isNotEmpty()) {
+ if (!activeTags.isNullOrEmpty()) {
_tagsView.setTags(activeTags);
_tagsView.visibility = View.VISIBLE;
} else {
@@ -262,7 +279,7 @@ abstract class FeedView : L
protected open fun setSortByOptions(options: List?) {
_sortByOptions = options;
- if (options != null && options.isNotEmpty()) {
+ if (!options.isNullOrEmpty()) {
val allOptions = arrayListOf();
allOptions.add("Default");
allOptions.addAll(options);
@@ -277,19 +294,19 @@ abstract class FeedView : L
}
}
protected abstract fun createAdapter(recyclerResults: RecyclerView, context: Context, dataset: ArrayList): InsertedViewAdapterWithLoader;
- protected abstract fun createLayoutManager(recyclerResults: RecyclerView, context: Context): LinearLayoutManager;
- protected open fun onRestoreCachedData(cachedData: RecyclerData, LinearLayoutManager, TPager, TResult, TConverted, InsertedViewHolder>) {}
+ protected abstract fun createLayoutManager(recyclerResults: RecyclerView, context: Context): StaggeredGridLayoutManager;
+ protected open fun onRestoreCachedData(cachedData: RecyclerData, StaggeredGridLayoutManager, TPager, TResult, TConverted, InsertedViewHolder>) {}
protected fun setProgress(fin: Int, total: Int) {
val progress = (fin.toFloat() / total);
- _progress_bar.progress = progress;
+ _progressBar.progress = progress;
if(progress > 0 && progress < 1)
{
- if(_progress_bar.height == 0)
- _progress_bar.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 5);
+ if(_progressBar.height == 0)
+ _progressBar.layoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 5);
}
- else if(_progress_bar.height > 0) {
- _progress_bar.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
+ else if(_progressBar.height > 0) {
+ _progressBar.layoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
}
}
@@ -345,7 +362,7 @@ abstract class FeedView : L
//insertPagerResults(_cache!!.cachePager.getResults(), false);
}
fun setPager(pager: TPager, cache: ItemCache? = null) {
- synchronized(_pager_lock) {
+ synchronized(_pagerLock) {
detachParentPagerEvents();
detachPagerEvents();
@@ -425,7 +442,7 @@ abstract class FeedView : L
val p = recyclerData.pager;
if(p is IReplacerPager<*>) {
p.onReplaced.subscribe(this) { _, newItem ->
- synchronized(_pager_lock) {
+ synchronized(_pagerLock) {
val filtered = filterResults(listOf(newItem as TResult));
if(filtered.isEmpty())
return@subscribe;
@@ -443,7 +460,7 @@ abstract class FeedView : L
var _lastNextPage = false;
private fun loadNextPage() {
- synchronized(_pager_lock) {
+ synchronized(_pagerLock) {
val pager: TPager = recyclerData.pager ?: return;
val hasMorePages = pager.hasMorePages();
Logger.i(TAG, "loadNextPage() hasMorePages=$hasMorePages, page size=${pager.getResults().size}");
@@ -468,7 +485,7 @@ abstract class FeedView : L
}
companion object {
- private val TAG = "FeedView";
+ private const val TAG = "FeedView";
}
abstract class ItemCache(val cachePager: IPager) {
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
index 3ddddbf0..beaf315d 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
@@ -6,7 +6,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.futo.platformplayer.*
import com.futo.platformplayer.activities.MainActivity
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
@@ -18,13 +18,9 @@ import com.futo.platformplayer.engine.exceptions.ScriptCaptchaRequiredException
import com.futo.platformplayer.engine.exceptions.ScriptExecutionException
import com.futo.platformplayer.engine.exceptions.ScriptImplementationException
import com.futo.platformplayer.logging.Logger
-import com.futo.platformplayer.models.SearchType
-import com.futo.platformplayer.states.AnnouncementType
-import com.futo.platformplayer.states.StateAnnouncement
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.states.StateMeta
import com.futo.platformplayer.states.StatePlatform
-import com.futo.platformplayer.states.StateSubscriptions
import com.futo.platformplayer.views.FeedStyle
import com.futo.platformplayer.views.NoResultsView
import com.futo.platformplayer.views.adapters.ContentPreviewViewHolder
@@ -32,11 +28,8 @@ import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
import com.futo.platformplayer.views.adapters.InsertedViewHolder
import com.futo.platformplayer.views.announcements.AnnouncementView
import com.futo.platformplayer.views.buttons.BigButton
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.time.OffsetDateTime
-import java.util.UUID
class HomeFragment : MainFragment() {
override val isMainView : Boolean = true;
@@ -44,7 +37,7 @@ class HomeFragment : MainFragment() {
override val hasBottomBar: Boolean get() = true;
private var _view: HomeView? = null;
- private var _cachedRecyclerData: FeedView.RecyclerData, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null;
+ private var _cachedRecyclerData: FeedView.RecyclerData, StaggeredGridLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null;
fun reloadFeed() {
_view?.reloadFeed()
@@ -101,15 +94,14 @@ class HomeFragment : MainFragment() {
class HomeView : ContentFeedView {
override val feedStyle: FeedStyle get() = Settings.instance.home.getHomeFeedStyle();
- private var _announcementsView: AnnouncementView;
+ private var _announcementsView: AnnouncementView = AnnouncementView(context, null).apply {
+ headerView.addView(this);
+ };
private val _taskGetPager: TaskHandler>;
override val shouldShowTimeBar: Boolean get() = Settings.instance.home.progressBar
- constructor(fragment: HomeFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData) {
- _announcementsView = AnnouncementView(context, null).apply {
- headerView.addView(this);
- };
+ constructor(fragment: HomeFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, StaggeredGridLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData) {;
_taskGetPager = TaskHandler>({ fragment.lifecycleScope }, {
StatePlatform.instance.getHomeRefresh(fragment.lifecycleScope)
@@ -174,7 +166,7 @@ class HomeFragment : MainFragment() {
loadResults();
}
- override fun getEmptyPagerView(): View? {
+ override fun getEmptyPagerView(): View {
val dp10 = 10.dp(resources);
val dp30 = 30.dp(resources);
@@ -206,8 +198,7 @@ class HomeFragment : MainFragment() {
listOf(BigButton(context, "Sources", "Go to the sources tab", R.drawable.ic_creators) {
fragment.navigate();
}.withMargin(dp10, dp30))
- );
- return null;
+ )
}
override fun reload() {
@@ -227,7 +218,7 @@ class HomeFragment : MainFragment() {
//StateAnnouncement.instance.registerAnnouncement(UUID.randomUUID().toString(), context.getString(R.string.no_home_available), context.getString(R.string.no_home_page_is_available_please_check_if_you_are_connected_to_the_internet_and_refresh), AnnouncementType.SESSION);
}
- Logger.i(TAG, "Got new home pager ${pager}");
+ Logger.i(TAG, "Got new home pager $pager");
finishRefreshLayoutLoader();
setLoading(false);
setPager(pager);
@@ -237,7 +228,7 @@ class HomeFragment : MainFragment() {
}
companion object {
- val TAG = "HomeFragment";
+ const val TAG = "HomeFragment";
fun newInstance() = HomeFragment().apply {}
}
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt
index 03d9a626..9f1964c8 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SubscriptionsFeedFragment.kt
@@ -7,10 +7,9 @@ import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.futo.platformplayer.*
import com.futo.platformplayer.activities.MainActivity
-import com.futo.platformplayer.api.media.IPlatformClient
import com.futo.platformplayer.api.media.models.contents.ContentType
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
@@ -46,7 +45,6 @@ import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
-import java.nio.channels.Channel
import java.time.OffsetDateTime
import kotlin.system.measureTimeMillis
@@ -57,7 +55,7 @@ class SubscriptionsFeedFragment : MainFragment() {
private var _view: SubscriptionsFeedView? = null;
private var _group: SubscriptionGroup? = null;
- private var _cachedRecyclerData: FeedView.RecyclerData, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null;
+ private var _cachedRecyclerData: FeedView.RecyclerData, StaggeredGridLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null;
override fun onShownWithView(parameter: Any?, isBack: Boolean) {
super.onShownWithView(parameter, isBack);
@@ -110,7 +108,7 @@ class SubscriptionsFeedFragment : MainFragment() {
var subGroup: SubscriptionGroup? = null;
- constructor(fragment: SubscriptionsFeedFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData) {
+ constructor(fragment: SubscriptionsFeedFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData, StaggeredGridLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>? = null) : super(fragment, inflater, cachedRecyclerData) {
Logger.i(TAG, "SubscriptionsFeedFragment constructor()");
StateSubscriptions.instance.global.onUpdateProgress.subscribe(this) { progress, total ->
};
@@ -214,7 +212,7 @@ class SubscriptionsFeedFragment : MainFragment() {
val subRequestCounts = StateSubscriptions.instance.getSubscriptionRequestCount(group);
val reqCountStr = subRequestCounts.map { " ${it.key.config.name}: ${it.value}/${it.key.getSubscriptionRateLimit()}" }.joinToString("\n");
val rateLimitPlugins = subRequestCounts.filter { clientCount -> clientCount.key.getSubscriptionRateLimit()?.let { rateLimit -> clientCount.value > rateLimit } == true }
- Logger.w(TAG, "Trying to refreshing subscriptions with requests:\n" + reqCountStr);
+ Logger.w(TAG, "Trying to refreshing subscriptions with requests:\n$reqCountStr");
if(rateLimitPlugins.any())
throw RateLimitException(rateLimitPlugins.map { it.key.id });
}
@@ -276,7 +274,7 @@ class SubscriptionsFeedFragment : MainFragment() {
private fun initializeToolbarContent() {
_subscriptionBar = SubscriptionBar(context).apply {
- layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
};
_subscriptionBar?.onClickChannel?.subscribe { c -> fragment.navigate(c); };
_subscriptionBar?.onToggleGroup?.subscribe { g ->
@@ -395,7 +393,7 @@ class SubscriptionsFeedFragment : MainFragment() {
_taskGetPager.run(withRefetch);
}
- override fun onRestoreCachedData(cachedData: RecyclerData, LinearLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>) {
+ override fun onRestoreCachedData(cachedData: RecyclerData, StaggeredGridLayoutManager, IPager, IPlatformContent, IPlatformContent, InsertedViewHolder>) {
super.onRestoreCachedData(cachedData);
setEmptyPager(cachedData.results.isEmpty());
}
@@ -450,7 +448,7 @@ class SubscriptionsFeedFragment : MainFragment() {
if (toShow is PluginException)
UIDialogs.appToast(ToastView.Toast(
toShow.message +
- (if(channel != null) "\nChannel: " + channel else ""), false, null,
+ (if(channel != null) "\nChannel: $channel" else ""), false, null,
"Plugin ${toShow.config.name} failed")
);
else
@@ -461,14 +459,14 @@ class SubscriptionsFeedFragment : MainFragment() {
val failedChannels = exs.filterIsInstance().map { it.channelNameOrUrl }.distinct().toList();
val failedPlugins = exs.filter { it is PluginException || (it is ChannelException && it.cause is PluginException) }
.map { if(it is ChannelException) (it.cause as PluginException) else if(it is PluginException) it else null }
- .filter { it != null }
+ .filterNotNull()
.distinctBy { it?.config?.name }
.map { it!! }
.toList();
for(distinctPluginFail in failedPlugins)
UIDialogs.appToast(context.getString(R.string.plugin_pluginname_failed_message).replace("{pluginName}", distinctPluginFail.config.name).replace("{message}", distinctPluginFail.message ?: ""));
if(failedChannels.isNotEmpty())
- UIDialogs.appToast(ToastView.Toast(failedChannels.take(3).map { "- ${it}" }.joinToString("\n") +
+ UIDialogs.appToast(ToastView.Toast(failedChannels.take(3).map { "- $it" }.joinToString("\n") +
(if(failedChannels.size >= 3) "\nAnd ${failedChannels.size - 3} more" else ""), false, null, "Failed Channels"));
}
} catch (e: Throwable) {
@@ -480,7 +478,7 @@ class SubscriptionsFeedFragment : MainFragment() {
}
companion object {
- val TAG = "SubscriptionsFeedFragment";
+ const val TAG = "SubscriptionsFeedFragment";
fun newInstance() = SubscriptionsFeedFragment().apply {}
}
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/TutorialFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/TutorialFragment.kt
index 5139c0f8..3bc9a9c5 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/TutorialFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/TutorialFragment.kt
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
+import android.widget.ScrollView
import android.widget.TextView
import com.futo.platformplayer.*
import com.futo.platformplayer.api.media.IPlatformClient
@@ -58,7 +59,15 @@ class TutorialFragment : MainFragment() {
}
@SuppressLint("ViewConstructor")
- class TutorialView : LinearLayout {
+ class TutorialView(fragment: TutorialFragment, inflater: LayoutInflater) :
+ ScrollView(inflater.context) {
+ init {
+ addView(TutorialContainer(fragment, inflater))
+ }
+ }
+
+ @SuppressLint("ViewConstructor")
+ class TutorialContainer : LinearLayout {
val fragment: TutorialFragment
constructor(fragment: TutorialFragment, inflater: LayoutInflater) : super(inflater.context) {
@@ -150,7 +159,7 @@ class TutorialFragment : MainFragment() {
}
companion object {
- val TAG = "HomeFragment";
+ const val TAG = "HomeFragment";
fun newInstance() = TutorialFragment().apply {}
val initialSetupVideos = listOf(
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt
index b1a498f5..faf20a79 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt
@@ -1,11 +1,10 @@
package com.futo.platformplayer.fragment.mainactivity.main
+import android.annotation.SuppressLint
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
-import android.os.Handler
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -14,10 +13,8 @@ import android.view.WindowInsetsController
import android.view.WindowManager
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.view.WindowCompat
-import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
-import com.futo.platformplayer.SimpleOrientationListener
import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.activities.SettingsActivity
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
@@ -25,12 +22,12 @@ import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
import com.futo.platformplayer.casting.StateCasting
import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.constructs.Event1
-import com.futo.platformplayer.listeners.AutoRotateChangeListener
import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.models.PlatformVideoWithTime
import com.futo.platformplayer.models.UrlVideoWithTime
import com.futo.platformplayer.states.StatePlayer
import com.futo.platformplayer.views.containers.SingleViewTouchableMotionLayout
+import kotlin.math.min
class VideoDetailFragment : MainFragment {
@@ -43,11 +40,10 @@ class VideoDetailFragment : MainFragment {
private var _viewDetail : VideoDetailView? = null;
private var _view : SingleViewTouchableMotionLayout? = null;
- private lateinit var _autoRotateChangeListener: AutoRotateChangeListener
- private lateinit var _orientationListener: SimpleOrientationListener
- private var _currentOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- var isFullscreen : Boolean = false;
+ private var isFullscreen : Boolean = false;
+ var isMinimizing : Boolean = false;
+ private var isSmallWindow : Boolean = true;
val onFullscreenChanged = Event1();
var isTransitioning : Boolean = false
private set;
@@ -77,8 +73,7 @@ class VideoDetailFragment : MainFragment {
private var _leavingPiP = false;
//region Fragment
- constructor() : super() {
- }
+ constructor() : super()
fun nextVideo() {
_viewDetail?.nextVideo(true, true, true);
@@ -88,44 +83,74 @@ class VideoDetailFragment : MainFragment {
_viewDetail?.prevVideo(true);
}
- private fun onStateChanged(state: VideoDetailFragment.State) {
+ fun detectWindowSize() {
+ isSmallWindow = min(
+ resources.configuration.screenWidthDp,
+ resources.configuration.screenHeightDp
+ ) < resources.getDimension(R.dimen.landscape_threshold)
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+
+ detectWindowSize()
+
+ if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE && !isFullscreen && state == State.MAXIMIZED) {
+ _viewDetail?.setFullscreen(true)
+ }
+
+ if (isFullscreen && !Settings.instance.playback.fullscreenPortrait && newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
+ _viewDetail?.setFullscreen(false)
+ }
+ }
+
+ private fun onStateChanged(state: State) {
+ if (isSmallWindow && state == State.MAXIMIZED && !isFullscreen && resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ _viewDetail?.setFullscreen(true)
+ }
+
updateOrientation()
}
- private fun updateOrientation() {
+ @SuppressLint("SourceLockedOrientationActivity")
+ fun updateOrientation() {
val a = activity ?: return
- val isMaximized = state == State.MAXIMIZED
val isFullScreenPortraitAllowed = Settings.instance.playback.fullscreenPortrait;
- val bypassRotationPrevention = Settings.instance.other.bypassRotationPrevention;
- val currentRequestedOrientation = a.requestedOrientation
- var currentOrientation = if (_currentOrientation == -1) currentRequestedOrientation else _currentOrientation
- if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT && !Settings.instance.playback.reversePortrait)
- currentOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ val isReversePortraitAllowed = Settings.instance.playback.reversePortrait;
+ val rotationLock = StatePlayer.instance.rotationLock
- val isAutoRotate = Settings.instance.playback.isAutoRotate()
- val isFs = isFullscreen
-
- if (isFs && isMaximized) {
- if (isFullScreenPortraitAllowed) {
- if (isAutoRotate) {
- a.requestedOrientation = currentOrientation
- }
- } else if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) {
- if (isAutoRotate || currentOrientation != currentRequestedOrientation && (currentRequestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || currentRequestedOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT)) {
- a.requestedOrientation = currentOrientation
- }
- } else {
- a.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
- }
- } else if (bypassRotationPrevention) {
- a.requestedOrientation = currentOrientation
- } else if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) {
- a.requestedOrientation = currentOrientation
- } else {
- a.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ // For small windows if the device isn't landscape right now and full screen portrait isn't allowed then we should force landscape
+ if (isSmallWindow && isFullscreen && !isFullScreenPortraitAllowed && resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT && !rotationLock) {
+ activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
}
+ // For small windows if the device isn't in a portrait orientation and we're in the maximized state then we should force portrait
+ else if (isSmallWindow && !isMinimizing && !isFullscreen && state == State.MAXIMIZED && resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
+ } else if (rotationLock) {
+ a.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
+ } else {
+ when (Settings.instance.playback.autoRotate) {
+ 0 -> {
+ a.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
+ }
- Log.i(TAG, "updateOrientation (isFs = ${isFs}, currentOrientation = ${currentOrientation}, currentRequestedOrientation = ${currentRequestedOrientation}, isMaximized = ${isMaximized}, isAutoRotate = ${isAutoRotate}, isFullScreenPortraitAllowed = ${isFullScreenPortraitAllowed}) resulted in requested orientation ${activity?.requestedOrientation}");
+ 1 -> {
+ a.requestedOrientation = if (isReversePortraitAllowed) {
+ ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+ } else {
+ ActivityInfo.SCREEN_ORIENTATION_SENSOR
+ }
+ }
+
+ 2 -> {
+ a.requestedOrientation = if (isReversePortraitAllowed) {
+ ActivityInfo.SCREEN_ORIENTATION_FULL_USER
+ } else {
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ }
+ }
+ }
+ }
}
override fun onShownWithView(parameter: Any?, isBack: Boolean) {
@@ -167,10 +192,6 @@ class VideoDetailFragment : MainFragment {
return true;
}
- override fun onHide() {
- super.onHide();
- }
-
fun preventPictureInPicture() {
Logger.i(TAG, "preventPictureInPicture() preventPictureInPicture = true");
_viewDetail?.preventPictureInPicture = true;
@@ -211,6 +232,7 @@ class VideoDetailFragment : MainFragment {
it.applyFragment(this);
it.onFullscreenChanged.subscribe(::onFullscreenChanged);
it.onMinimize.subscribe {
+ isMinimizing = true
_view!!.transitionToStart();
};
it.onClose.subscribe {
@@ -247,6 +269,7 @@ class VideoDetailFragment : MainFragment {
if (state != State.MINIMIZED && progress < 0.1) {
state = State.MINIMIZED;
+ isMinimizing = false
onMinimize.emit();
}
else if (state != State.MAXIMIZED && progress > 0.9) {
@@ -285,13 +308,6 @@ class VideoDetailFragment : MainFragment {
minimizeVideoDetail();
}
- _autoRotateChangeListener = AutoRotateChangeListener(requireContext(), Handler()) { _ ->
- if (updateAutoFullscreen()) {
- return@AutoRotateChangeListener
- }
- updateOrientation()
- }
-
_loadUrlOnCreate?.let { _viewDetail?.setVideo(it.url, it.timeSeconds, it.playWhenReady) };
maximizeVideoDetail();
@@ -300,40 +316,11 @@ class VideoDetailFragment : MainFragment {
}
StatePlayer.instance.onRotationLockChanged.subscribe(this) {
- if (updateAutoFullscreen()) {
- return@subscribe
- }
- updateOrientation()
- }
-
- _orientationListener = SimpleOrientationListener(requireActivity(), lifecycleScope)
- _orientationListener.onOrientationChanged.subscribe {
- _currentOrientation = it
- Logger.i(TAG, "Current orientation changed (_currentOrientation = ${_currentOrientation})")
-
- if (updateAutoFullscreen()) {
- return@subscribe
- }
updateOrientation()
}
return _view!!;
}
- private fun updateAutoFullscreen(): Boolean {
- if (Settings.instance.playback.isAutoRotate()) {
- if (state == State.MAXIMIZED && !isFullscreen && (_currentOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || _currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE)) {
- _viewDetail?.setFullscreen(true)
- return true
- }
-
- if (state == State.MAXIMIZED && isFullscreen && !Settings.instance.playback.fullscreenPortrait && (_currentOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || _currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT)) {
- _viewDetail?.setFullscreen(false)
- return true
- }
- }
- return false
- }
-
fun onUserLeaveHint() {
val viewDetail = _viewDetail;
Logger.i(TAG, "onUserLeaveHint preventPictureInPicture=${viewDetail?.preventPictureInPicture} isCasting=${StateCasting.instance.isCasting} isBackgroundPictureInPicture=${Settings.instance.playback.isBackgroundPictureInPicture()} allowBackground=${viewDetail?.allowBackground}");
@@ -422,15 +409,12 @@ class VideoDetailFragment : MainFragment {
if(shouldStop) {
_viewDetail?.onStop();
StateCasting.instance.onStop();
- Logger.v(TAG, "called onStop() shouldStop: $shouldStop");
}
}
override fun onDestroyMainView() {
super.onDestroyMainView();
Logger.v(TAG, "onDestroyMainView");
- _autoRotateChangeListener?.unregister()
- _orientationListener.stopListening()
SettingsActivity.settingsActivityClosed.remove(this)
StatePlayer.instance.onRotationLockChanged.remove(this)
@@ -511,7 +495,7 @@ class VideoDetailFragment : MainFragment {
}
companion object {
- private val TAG = "VideoDetailFragment";
+ private const val TAG = "VideoDetailFragment";
fun newInstance() = VideoDetailFragment().apply {}
}
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt
index 6d44996f..089e9c83 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt
@@ -154,20 +154,19 @@ import com.futo.polycentric.core.Opinion
import com.futo.polycentric.core.toURLInfoSystemLinkUrl
import com.google.protobuf.ByteString
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
-import okhttp3.Dispatcher
-import org.w3c.dom.Text
import userpackage.Protocol
import java.time.OffsetDateTime
import kotlin.math.abs
import kotlin.math.roundToLong
-@androidx.media3.common.util.UnstableApi
+@UnstableApi
class VideoDetailView : ConstraintLayout {
private val TAG = "VideoDetailView"
@@ -180,7 +179,7 @@ class VideoDetailView : ConstraintLayout {
private var _searchVideo: IPlatformVideo? = null;
var video: IPlatformVideoDetails? = null
private set;
- var videoLocal: VideoLocal? = null;
+ private var videoLocal: VideoLocal? = null;
private var _playbackTracker: IPlaybackTracker? = null;
private var _historyIndex: DBHistory.Index? = null;
@@ -195,7 +194,7 @@ class VideoDetailView : ConstraintLayout {
private val _timeBar: TimeBar;
private var _upNext: UpNextView;
- val rootView: ConstraintLayout;
+ private val rootView: ConstraintLayout;
private val _title: TextView;
private val _subTitle: TextView;
@@ -284,7 +283,7 @@ class VideoDetailView : ConstraintLayout {
var isPlaying: Boolean = false
private set;
- var lastPositionMilliseconds: Long = 0
+ private var lastPositionMilliseconds: Long = 0
private set;
private var _historicalPosition: Long = 0;
private var _commentsCount = 0;
@@ -524,12 +523,14 @@ class VideoDetailView : ConstraintLayout {
_cast.onChapterChanged.subscribe(onChapterChanged);
_cast.onMinimizeClick.subscribe {
- _player.setFullScreen(false);
- onMinimize.emit();
+ // emit minimize before toggling fullscreen so we know that the full screen toggle is happening during a minimize operation
+ onMinimize.emit()
+ _player.setFullScreen(false)
};
_player.onMinimize.subscribe {
- _player.setFullScreen(false);
- onMinimize.emit();
+ // emit minimize before toggling fullscreen so we know that the full screen toggle is happening during a minimize operation
+ onMinimize.emit()
+ _player.setFullScreen(false)
};
_player.onTimeBarChanged.subscribe { position, _ ->
@@ -697,7 +698,8 @@ class VideoDetailView : ConstraintLayout {
if (c is PolycentricPlatformComment) {
var parentComment: PolycentricPlatformComment = c;
- _container_content_replies.load(if (_tabIndex!! == 0) false else true, metadata, c.contextUrl, c.reference, c,
+ _container_content_replies.load(
+ _tabIndex!! != 0, metadata, c.contextUrl, c.reference, c,
{ StatePolycentric.instance.getCommentPager(c.contextUrl, c.reference) },
{
val newComment = parentComment.cloneWithUpdatedReplyCount((parentComment.replyCount ?: 0) + 1);
@@ -705,7 +707,7 @@ class VideoDetailView : ConstraintLayout {
parentComment = newComment;
});
} else {
- _container_content_replies.load(if (_tabIndex!! == 0) false else true, metadata, null, null, c, { StatePlatform.instance.getSubComments(c) });
+ _container_content_replies.load(_tabIndex!! != 0, metadata, null, null, c, { StatePlatform.instance.getSubComments(c) });
}
switchContentView(_container_content_replies);
};
@@ -887,7 +889,7 @@ class VideoDetailView : ConstraintLayout {
else {
val selectedButtons = _buttonPinStore.getAllValues()
.map { x-> buttons.find { it.tagRef == x } }
- .filter { it != null }
+ .filterNotNull()
.map { it!! };
_buttonPins.setButtons(*(selectedButtons +
buttons.filter { !selectedButtons.contains(it) } +
@@ -1201,7 +1203,7 @@ class VideoDetailView : ConstraintLayout {
switchContentView(_container_content_main);
}
- //@OptIn(ExperimentalCoroutinesApi::class)
+ @OptIn(ExperimentalCoroutinesApi::class)
fun setVideoDetails(videoDetail: IPlatformVideoDetails, newVideo: Boolean = false) {
Logger.i(TAG, "setVideoDetails (${videoDetail.name})")
_didTriggerDatasourceErrroCount = 0;
@@ -1870,7 +1872,7 @@ class VideoDetailView : ConstraintLayout {
?.map { x -> VideoHelper.selectBestVideoSource(videoSources.filter { x == it.height * it.width }, -1, FutoVideoPlayerBase.PREFERED_VIDEO_CONTAINERS) }
?.plus(videoSources.filter { it is IHLSManifestSource || it is IDashManifestSource }))
?.distinct()
- ?.filter { it != null }
+ ?.filterNotNull()
?.toList() ?: listOf() else videoSources?.toList() ?: listOf()
val bestAudioContainer = audioSources?.let { VideoHelper.selectBestAudioSource(it, FutoVideoPlayerBase.PREFERED_AUDIO_CONTAINERS)?.container };
val bestAudioSources = if(doDedup) audioSources
@@ -2171,7 +2173,7 @@ class VideoDetailView : ConstraintLayout {
cleanupPlaybackTracker();
val url = _url;
- if (url != null && url.isNotBlank()) {
+ if (!url.isNullOrBlank()) {
setLoading(true);
_taskLoadVideo.run(url);
}
@@ -2183,7 +2185,7 @@ class VideoDetailView : ConstraintLayout {
if(fullscreen) {
_layoutPlayerContainer.setPadding(0, 0, 0, 0);
- val lp = _container_content.layoutParams as ConstraintLayout.LayoutParams;
+ val lp = _container_content.layoutParams as LayoutParams;
lp.topMargin = 0;
_container_content.layoutParams = lp;
@@ -2196,7 +2198,7 @@ class VideoDetailView : ConstraintLayout {
else {
_layoutPlayerContainer.setPadding(0, 0, 0, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6.0f, Resources.getSystem().displayMetrics).toInt());
- val lp = _container_content.layoutParams as ConstraintLayout.LayoutParams;
+ val lp = _container_content.layoutParams as LayoutParams;
lp.topMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, -18.0f, Resources.getSystem().displayMetrics).toInt();
_container_content.layoutParams = lp;
@@ -2239,7 +2241,7 @@ class VideoDetailView : ConstraintLayout {
fun setFullscreen(fullscreen : Boolean) {
Logger.i(TAG, "setFullscreen(fullscreen=$fullscreen)")
- _player.setFullScreen(fullscreen);
+ _player.setFullScreen(fullscreen)
}
private fun setLoading(isLoading : Boolean) {
if(isLoading){
diff --git a/app/src/main/java/com/futo/platformplayer/listeners/AutoRotateChangeListener.kt b/app/src/main/java/com/futo/platformplayer/listeners/AutoRotateChangeListener.kt
deleted file mode 100644
index 12efb3aa..00000000
--- a/app/src/main/java/com/futo/platformplayer/listeners/AutoRotateChangeListener.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.futo.platformplayer.listeners
-
-import android.content.Context
-import android.database.ContentObserver
-import android.os.Handler
-import android.provider.Settings
-
-class AutoRotateObserver(handler: Handler, private val onChangeCallback: () -> Unit) : ContentObserver(handler) {
- override fun onChange(selfChange: Boolean) {
- super.onChange(selfChange)
- onChangeCallback()
- }
-}
-
-class AutoRotateChangeListener(context: Context, handler: Handler, private val onAutoRotateChanged: (Boolean) -> Unit) {
-
- private val contentResolver = context.contentResolver
- private val autoRotateObserver = AutoRotateObserver(handler) {
- val isAutoRotateEnabled = isAutoRotateEnabled()
- onAutoRotateChanged(isAutoRotateEnabled)
- }
-
- init {
- contentResolver.registerContentObserver(
- Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
- false,
- autoRotateObserver
- )
- }
-
- fun unregister() {
- contentResolver.unregisterContentObserver(autoRotateObserver)
- }
-
- private fun isAutoRotateEnabled(): Boolean {
- return Settings.System.getInt(
- contentResolver,
- Settings.System.ACCELEROMETER_ROTATION,
- 0
- ) == 1
- }
-}
diff --git a/app/src/main/res/values/dimensions.xml b/app/src/main/res/values/dimensions.xml
index d3c299e7..320998e2 100644
--- a/app/src/main/res/values/dimensions.xml
+++ b/app/src/main/res/values/dimensions.xml
@@ -2,4 +2,5 @@
200dp
-
\ No newline at end of file
+ 300dp
+
diff --git a/app/src/unstable/AndroidManifest.xml b/app/src/unstable/AndroidManifest.xml
index a30bb7af..1304222e 100644
--- a/app/src/unstable/AndroidManifest.xml
+++ b/app/src/unstable/AndroidManifest.xml
@@ -7,7 +7,8 @@
-
+