This commit is contained in:
Kelvin 2024-08-22 21:01:42 +02:00
commit a95ddab814
17 changed files with 398 additions and 266 deletions

View file

@ -147,6 +147,8 @@ android {
} }
dependencies { dependencies {
implementation 'com.google.dagger:dagger:2.48'
annotationProcessor 'com.google.dagger:dagger-compiler:2.48'
//Core //Core
implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.core:core-ktx:1.12.0'

View file

@ -11,6 +11,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/> <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<!--<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions"/> <uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions"/>
@ -50,7 +51,7 @@
android:name=".activities.MainActivity" android:name=".activities.MainActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true" android:exported="true"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" android:theme="@style/Theme.FutoVideo.NoActionBar"
android:launchMode="singleTask" android:launchMode="singleTask"
android:resizeableActivity="true" android:resizeableActivity="true"
@ -152,27 +153,27 @@
<activity <activity
android:name=".activities.SettingsActivity" android:name=".activities.SettingsActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.DeveloperActivity" android:name=".activities.DeveloperActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.ExceptionActivity" android:name=".activities.ExceptionActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.CaptchaActivity" android:name=".activities.CaptchaActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.LoginActivity" android:name=".activities.LoginActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.AddSourceActivity" android:name=".activities.AddSourceActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:exported="true" android:exported="true"
android:theme="@style/Theme.FutoVideo.NoActionBar"> android:theme="@style/Theme.FutoVideo.NoActionBar">
<intent-filter> <intent-filter>
@ -186,44 +187,44 @@
</activity> </activity>
<activity <activity
android:name=".activities.AddSourceOptionsActivity" android:name=".activities.AddSourceOptionsActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.PolycentricHomeActivity" android:name=".activities.PolycentricHomeActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.PolycentricBackupActivity" android:name=".activities.PolycentricBackupActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.PolycentricCreateProfileActivity" android:name=".activities.PolycentricCreateProfileActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.PolycentricProfileActivity" android:name=".activities.PolycentricProfileActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.PolycentricWhyActivity" android:name=".activities.PolycentricWhyActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.PolycentricImportProfileActivity" android:name=".activities.PolycentricImportProfileActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.ManageTabsActivity" android:name=".activities.ManageTabsActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.QRCaptureActivity" android:name=".activities.QRCaptureActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
<activity <activity
android:name=".activities.FCastGuideActivity" android:name=".activities.FCastGuideActivity"
android:screenOrientation="portrait" android:screenOrientation="sensorPortrait"
android:theme="@style/Theme.FutoVideo.NoActionBar" /> android:theme="@style/Theme.FutoVideo.NoActionBar" />
</application> </application>
</manifest> </manifest>

View file

@ -0,0 +1,114 @@
import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
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 AdvancedOrientationListener(private val activity: Activity, private val lifecycleScope: CoroutineScope) {
private val sensorManager: SensorManager = activity.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val accelerometer: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
private val magnetometer: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
private var lastOrientation: Int = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
private var lastStableOrientation: Int = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
private var lastOrientationChangeTime = 0L
private val debounceTime = 200L
private val stabilityThresholdTime = 800L
private var deviceAspectRatio: Float = 1.0f
private val gravity = FloatArray(3)
private val geomagnetic = FloatArray(3)
private val rotationMatrix = FloatArray(9)
private val orientationAngles = FloatArray(3)
val onOrientationChanged = Event1<Int>()
private val sensorListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
when (event.sensor.type) {
Sensor.TYPE_ACCELEROMETER -> {
System.arraycopy(event.values, 0, gravity, 0, gravity.size)
}
Sensor.TYPE_MAGNETIC_FIELD -> {
System.arraycopy(event.values, 0, geomagnetic, 0, geomagnetic.size)
}
}
if (gravity.isNotEmpty() && geomagnetic.isNotEmpty()) {
val success = SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)
if (success) {
SensorManager.getOrientation(rotationMatrix, orientationAngles)
val azimuth = Math.toDegrees(orientationAngles[0].toDouble()).toFloat()
val pitch = Math.toDegrees(orientationAngles[1].toDouble()).toFloat()
val roll = Math.toDegrees(orientationAngles[2].toDouble()).toFloat()
val newOrientation = when {
roll in -155f .. -15f && isWithinThreshold(pitch, 0f, 30.0) -> {
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
roll in 15f .. 155f && isWithinThreshold(pitch, 0f, 30.0) -> {
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
}
isWithinThreshold(pitch, -90f, 30.0 * deviceAspectRatio) && roll in -15f .. 15f -> {
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
isWithinThreshold(pitch, 90f, 30.0 * deviceAspectRatio) && roll in -15f .. 15f -> {
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
}
else -> lastOrientation
}
//Logger.i("AdvancedOrientationListener", "newOrientation = ${newOrientation}, roll = ${roll}, pitch = ${pitch}, azimuth = ${azimuth}")
if (newOrientation != lastStableOrientation) {
val currentTime = System.currentTimeMillis()
if (currentTime - lastOrientationChangeTime > debounceTime) {
lastOrientationChangeTime = currentTime
lastStableOrientation = newOrientation
lifecycleScope.launch(Dispatchers.Main) {
delay(stabilityThresholdTime)
if (newOrientation == lastStableOrientation) {
lastOrientation = newOrientation
onOrientationChanged.emit(newOrientation)
}
}
}
}
}
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
private fun isWithinThreshold(value: Float, target: Float, threshold: Double): Boolean {
return Math.abs(value - target) <= threshold
}
init {
sensorManager.registerListener(sensorListener, accelerometer, SensorManager.SENSOR_DELAY_GAME)
sensorManager.registerListener(sensorListener, magnetometer, SensorManager.SENSOR_DELAY_GAME)
val metrics = activity.resources.displayMetrics
deviceAspectRatio = (metrics.heightPixels.toFloat() / metrics.widthPixels.toFloat())
if (deviceAspectRatio == 0.0f)
deviceAspectRatio = 1.0f
lastOrientation = activity.resources.configuration.orientation
}
fun stopListening() {
sensorManager.unregisterListener(sensorListener)
}
}

View file

@ -2,8 +2,11 @@ package com.futo.platformplayer
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Context import android.content.Context
import android.content.Context.POWER_SERVICE
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.webkit.CookieManager import android.webkit.CookieManager
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.activities.MainActivity import com.futo.platformplayer.activities.MainActivity
@ -23,6 +26,7 @@ import com.futo.platformplayer.states.StateBackup
import com.futo.platformplayer.states.StateCache import com.futo.platformplayer.states.StateCache
import com.futo.platformplayer.states.StateMeta import com.futo.platformplayer.states.StateMeta
import com.futo.platformplayer.states.StatePayment import com.futo.platformplayer.states.StatePayment
import com.futo.platformplayer.states.StatePlayer
import com.futo.platformplayer.states.StatePolycentric import com.futo.platformplayer.states.StatePolycentric
import com.futo.platformplayer.states.StateUpdate import com.futo.platformplayer.states.StateUpdate
import com.futo.platformplayer.stores.FragmentedStorage import com.futo.platformplayer.stores.FragmentedStorage
@ -34,6 +38,7 @@ import com.futo.platformplayer.views.fields.FormField
import com.futo.platformplayer.views.fields.FormFieldButton import com.futo.platformplayer.views.fields.FormFieldButton
import com.futo.platformplayer.views.fields.FormFieldWarning import com.futo.platformplayer.views.fields.FormFieldWarning
import com.futo.platformplayer.views.overlays.slideup.SlideUpMenuItem 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.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -44,6 +49,7 @@ import kotlinx.serialization.json.Json
import java.io.File import java.io.File
import java.time.OffsetDateTime import java.time.OffsetDateTime
@Serializable @Serializable
data class MenuBottomBarSetting(val id: Int, var enabled: Boolean); data class MenuBottomBarSetting(val id: Int, var enabled: Boolean);
@ -57,7 +63,7 @@ class Settings : FragmentedStorageFileJson() {
@Transient @Transient
val onTabsChanged = Event0(); val onTabsChanged = Event0();
@FormField(R.string.manage_polycentric_identity, FieldForm.BUTTON, R.string.manage_your_polycentric_identity, -6) @FormField(R.string.manage_polycentric_identity, FieldForm.BUTTON, R.string.manage_your_polycentric_identity, -7)
@FormFieldButton(R.drawable.ic_person) @FormFieldButton(R.drawable.ic_person)
fun managePolycentricIdentity() { fun managePolycentricIdentity() {
SettingsActivity.getActivity()?.let { SettingsActivity.getActivity()?.let {
@ -73,7 +79,7 @@ class Settings : FragmentedStorageFileJson() {
} }
} }
@FormField(R.string.show_faq, FieldForm.BUTTON, R.string.get_answers_to_common_questions, -5) @FormField(R.string.show_faq, FieldForm.BUTTON, R.string.get_answers_to_common_questions, -6)
@FormFieldButton(R.drawable.ic_quiz) @FormFieldButton(R.drawable.ic_quiz)
fun openFAQ() { fun openFAQ() {
try { try {
@ -83,7 +89,7 @@ class Settings : FragmentedStorageFileJson() {
//Ignored //Ignored
} }
} }
@FormField(R.string.show_issues, FieldForm.BUTTON, R.string.a_list_of_user_reported_and_self_reported_issues, -4) @FormField(R.string.show_issues, FieldForm.BUTTON, R.string.a_list_of_user_reported_and_self_reported_issues, -5)
@FormFieldButton(R.drawable.ic_data_alert) @FormFieldButton(R.drawable.ic_data_alert)
fun openIssues() { fun openIssues() {
try { try {
@ -115,7 +121,7 @@ class Settings : FragmentedStorageFileJson() {
} }
}*/ }*/
@FormField(R.string.manage_tabs, FieldForm.BUTTON, R.string.change_tabs_visible_on_the_home_screen, -3) @FormField(R.string.manage_tabs, FieldForm.BUTTON, R.string.change_tabs_visible_on_the_home_screen, -4)
@FormFieldButton(R.drawable.ic_tabs) @FormFieldButton(R.drawable.ic_tabs)
fun manageTabs() { fun manageTabs() {
try { try {
@ -129,7 +135,7 @@ class Settings : FragmentedStorageFileJson() {
@FormField(R.string.import_data, FieldForm.BUTTON, R.string.import_data_description, -2) @FormField(R.string.import_data, FieldForm.BUTTON, R.string.import_data_description, -3)
@FormFieldButton(R.drawable.ic_move_up) @FormFieldButton(R.drawable.ic_move_up)
fun import() { fun import() {
val act = SettingsActivity.getActivity() ?: return; val act = SettingsActivity.getActivity() ?: return;
@ -138,7 +144,7 @@ class Settings : FragmentedStorageFileJson() {
act.startActivity(intent); act.startActivity(intent);
} }
@FormField(R.string.link_handling, FieldForm.BUTTON, R.string.allow_grayjay_to_handle_links, -1) @FormField(R.string.link_handling, FieldForm.BUTTON, R.string.allow_grayjay_to_handle_links, -2)
@FormFieldButton(R.drawable.ic_link) @FormFieldButton(R.drawable.ic_link)
fun manageLinks() { fun manageLinks() {
try { try {
@ -148,6 +154,24 @@ class Settings : FragmentedStorageFileJson() {
} }
} }
/*@FormField(R.string.disable_battery_optimization, FieldForm.BUTTON, R.string.click_to_go_to_battery_optimization_settings_disabling_battery_optimization_will_prevent_the_os_from_killing_media_sessions, -1)
@FormFieldButton(R.drawable.battery_full_24px)
fun ignoreBatteryOptimization() {
SettingsActivity.getActivity()?.let {
val intent = Intent()
val packageName = it.packageName
val pm = it.getSystemService(POWER_SERVICE) as PowerManager;
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
intent.setAction(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
intent.setData(Uri.parse("package:$packageName"))
it.startActivity(intent)
UIDialogs.toast(it, "Please ignore battery optimizations for Grayjay")
} else {
UIDialogs.toast(it, "Battery optimizations already disabled for Grayjay")
}
}
}*/
@FormField(R.string.language, "group", -1, 0) @FormField(R.string.language, "group", -1, 0)
var language = LanguageSettings(); var language = LanguageSettings();
@Serializable @Serializable
@ -393,15 +417,7 @@ class Settings : FragmentedStorageFileJson() {
@DropdownFieldOptionsId(R.array.system_enabled_disabled_array) @DropdownFieldOptionsId(R.array.system_enabled_disabled_array)
var autoRotate: Int = 2; var autoRotate: Int = 2;
fun isAutoRotate() = autoRotate == 1 || (autoRotate == 2 && StateApp.instance.getCurrentSystemAutoRotate()); fun isAutoRotate() = (autoRotate == 1 && !StatePlayer.instance.rotationLock) || (autoRotate == 2 && StateApp.instance.getCurrentSystemAutoRotate() && !StatePlayer.instance.rotationLock);
@FormField(R.string.auto_rotate_dead_zone, FieldForm.DROPDOWN, R.string.this_prevents_the_device_from_rotating_within_the_given_amount_of_degrees, 6)
@DropdownFieldOptionsId(R.array.auto_rotate_dead_zone)
var autoRotateDeadZone: Int = 0;
fun getAutoRotateDeadZoneDegrees(): Int {
return autoRotateDeadZone * 5;
}
@FormField(R.string.background_behavior, FieldForm.DROPDOWN, -1, 7) @FormField(R.string.background_behavior, FieldForm.DROPDOWN, -1, 7)
@DropdownFieldOptionsId(R.array.player_background_behavior) @DropdownFieldOptionsId(R.array.player_background_behavior)

View file

@ -0,0 +1,55 @@
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 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<Int>()
private val orientationListener = object : OrientationEventListener(activity, SensorManager.SENSOR_DELAY_UI) {
override fun onOrientationChanged(orientation: Int) {
val newOrientation = when {
orientation in 45..134 -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
orientation in 135..224 -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
orientation in 225..314 -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
orientation in 315..360 || orientation in 0..44 -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
else -> lastOrientation
}
if (newOrientation != lastStableOrientation) {
lastStableOrientation = newOrientation
lifecycleScope.launch(Dispatchers.Main) {
delay(stabilityThresholdTime)
if (newOrientation == lastStableOrientation) {
lastOrientation = newOrientation
onOrientationChanged.emit(newOrientation)
}
}
}
}
}
init {
orientationListener.enable()
lastOrientation = activity.resources.configuration.orientation
}
fun stopListening() {
orientationListener.disable()
}
}

View file

@ -39,7 +39,6 @@ import com.futo.platformplayer.fragment.mainactivity.topbar.GeneralTopBarFragmen
import com.futo.platformplayer.fragment.mainactivity.topbar.ImportTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.ImportTopBarFragment
import com.futo.platformplayer.fragment.mainactivity.topbar.NavigationTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.NavigationTopBarFragment
import com.futo.platformplayer.fragment.mainactivity.topbar.SearchTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.SearchTopBarFragment
import com.futo.platformplayer.listeners.OrientationManager
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.models.ImportCache import com.futo.platformplayer.models.ImportCache
import com.futo.platformplayer.states.* import com.futo.platformplayer.states.*
@ -131,9 +130,6 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
val onNavigated = Event1<MainFragment>(); val onNavigated = Event1<MainFragment>();
private lateinit var _orientationManager: OrientationManager;
var orientation: OrientationManager.Orientation = OrientationManager.Orientation.PORTRAIT
private set;
private var _isVisible = true; private var _isVisible = true;
private var _wasStopped = false; private var _wasStopped = false;
@ -413,26 +409,6 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
.commitNow(); .commitNow();
defaultTab.action(_fragBotBarMenu); defaultTab.action(_fragBotBarMenu);
_orientationManager = OrientationManager(this);
_orientationManager.onOrientationChanged.subscribe {
orientation = it;
Logger.i(TAG, "Orientation changed (Found ${it})");
fragCurrent.onOrientationChanged(it);
if(_fragVideoDetail.state == VideoDetailFragment.State.MAXIMIZED)
_fragVideoDetail.onOrientationChanged(it);
else if(Settings.instance.other.bypassRotationPrevention)
{
requestedOrientation = when(orientation) {
OrientationManager.Orientation.PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
OrientationManager.Orientation.LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
OrientationManager.Orientation.REVERSED_PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
OrientationManager.Orientation.REVERSED_LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
}
}
};
_orientationManager.enable();
StateSubscriptions.instance; StateSubscriptions.instance;
fragCurrent.onShown(null, false); fragCurrent.onShown(null, false);
@ -529,17 +505,6 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
override fun onResume() { override fun onResume() {
super.onResume(); super.onResume();
Logger.v(TAG, "onResume") Logger.v(TAG, "onResume")
val curOrientation = _orientationManager.orientation;
if(_fragVideoDetail.state == VideoDetailFragment.State.MAXIMIZED && _fragVideoDetail.lastOrientation != curOrientation) {
Logger.i(TAG, "Orientation mismatch (Found ${curOrientation})");
orientation = curOrientation;
fragCurrent.onOrientationChanged(curOrientation);
if(_fragVideoDetail.state == VideoDetailFragment.State.MAXIMIZED)
_fragVideoDetail.onOrientationChanged(curOrientation);
}
_isVisible = true; _isVisible = true;
} }
@ -940,18 +905,6 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
override fun onRestart() { override fun onRestart() {
super.onRestart(); super.onRestart();
Logger.i(TAG, "onRestart"); Logger.i(TAG, "onRestart");
//Force Portrait on restart
Logger.i(TAG, "Restarted with state ${_fragVideoDetail.state}");
if(_fragVideoDetail.state != VideoDetailFragment.State.MAXIMIZED) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
WindowCompat.setDecorFitsSystemWindows(window, true)
WindowInsetsControllerCompat(window, rootView).let { controller ->
controller.show(WindowInsetsCompat.Type.statusBars());
controller.show(WindowInsetsCompat.Type.systemBars())
}
_fragVideoDetail.onOrientationChanged(OrientationManager.Orientation.PORTRAIT);
}
} }
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) { override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
@ -966,9 +919,6 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy(); super.onDestroy();
Logger.v(TAG, "onDestroy") Logger.v(TAG, "onDestroy")
_orientationManager.disable();
StateApp.instance.mainAppDestroyed(this); StateApp.instance.mainAppDestroyed(this);
} }

View file

@ -18,6 +18,7 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.* import com.futo.platformplayer.*
import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.states.StateApp import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.views.LoaderView import com.futo.platformplayer.views.LoaderView
@ -184,12 +185,19 @@ class SettingsActivity : AppCompatActivity(), IWithResultLauncher {
resultLauncher.launch(intent); resultLauncher.launch(intent);
} }
override fun onDestroy() {
super.onDestroy()
settingsActivityClosed.emit()
}
companion object { companion object {
//TODO: Temporary for solving Settings issues //TODO: Temporary for solving Settings issues
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
private var _lastActivity: SettingsActivity? = null; private var _lastActivity: SettingsActivity? = null;
val settingsActivityClosed = Event0()
fun getActivity(): SettingsActivity? { fun getActivity(): SettingsActivity? {
val act = _lastActivity; val act = _lastActivity;
if(act != null && !act._isFinished) if(act != null && !act._isFinished)

View file

@ -8,7 +8,6 @@ import com.futo.platformplayer.activities.MainActivity
import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.fragment.mainactivity.MainActivityFragment import com.futo.platformplayer.fragment.mainactivity.MainActivityFragment
import com.futo.platformplayer.fragment.mainactivity.topbar.TopFragment import com.futo.platformplayer.fragment.mainactivity.topbar.TopFragment
import com.futo.platformplayer.listeners.OrientationManager
abstract class MainFragment : MainActivityFragment() { abstract class MainFragment : MainActivityFragment() {
open val isMainView: Boolean = false; open val isMainView: Boolean = false;
@ -46,10 +45,6 @@ abstract class MainFragment : MainActivityFragment() {
} }
open fun onOrientationChanged(orientation: OrientationManager.Orientation) {
}
open fun onBackPressed(): Boolean { open fun onBackPressed(): Boolean {
return false; return false;
} }

View file

@ -3,30 +3,34 @@ package com.futo.platformplayer.fragment.mainactivity.main
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.res.Configuration import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowInsets
import android.view.WindowInsetsController
import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat import androidx.lifecycle.lifecycleScope
import androidx.core.view.WindowInsetsControllerCompat
import com.futo.platformplayer.R import com.futo.platformplayer.R
import com.futo.platformplayer.Settings import com.futo.platformplayer.Settings
import com.futo.platformplayer.SimpleOrientationListener
import com.futo.platformplayer.UIDialogs import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.activities.MainActivity import com.futo.platformplayer.activities.SettingsActivity
import com.futo.platformplayer.api.media.models.video.IPlatformVideo import com.futo.platformplayer.api.media.models.video.IPlatformVideo
import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
import com.futo.platformplayer.casting.CastConnectionState
import com.futo.platformplayer.casting.StateCasting import com.futo.platformplayer.casting.StateCasting
import com.futo.platformplayer.constructs.Event0 import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.listeners.OrientationManager import com.futo.platformplayer.listeners.AutoRotateChangeListener
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.models.PlatformVideoWithTime import com.futo.platformplayer.models.PlatformVideoWithTime
import com.futo.platformplayer.models.UrlVideoWithTime import com.futo.platformplayer.models.UrlVideoWithTime
import com.futo.platformplayer.states.StatePlayer import com.futo.platformplayer.states.StatePlayer
import com.futo.platformplayer.views.containers.SingleViewTouchableMotionLayout import com.futo.platformplayer.views.containers.SingleViewTouchableMotionLayout
class VideoDetailFragment : MainFragment { class VideoDetailFragment : MainFragment {
override val isMainView : Boolean = false; override val isMainView : Boolean = false;
override val hasBottomBar: Boolean = true; override val hasBottomBar: Boolean = true;
@ -37,6 +41,9 @@ class VideoDetailFragment : MainFragment {
private var _viewDetail : VideoDetailView? = null; private var _viewDetail : VideoDetailView? = null;
private var _view : SingleViewTouchableMotionLayout? = 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; var isFullscreen : Boolean = false;
val onFullscreenChanged = Event1<Boolean>(); val onFullscreenChanged = Event1<Boolean>();
@ -45,16 +52,21 @@ class VideoDetailFragment : MainFragment {
var isInPictureInPicture : Boolean = false var isInPictureInPicture : Boolean = false
private set; private set;
var state: State = State.CLOSED; private var _state: State = State.CLOSED
var state: State
get() = _state
set(value) {
_state = value
onStateChanged(value)
}
val currentUrl get() = _viewDetail?.currentUrl; val currentUrl get() = _viewDetail?.currentUrl;
val onMinimize = Event0(); val onMinimize = Event0();
val onTransitioning = Event1<Boolean>(); val onTransitioning = Event1<Boolean>();
val onMaximized = Event0(); val onMaximized = Event0();
var lastOrientation : OrientationManager.Orientation = OrientationManager.Orientation.PORTRAIT
private set;
private var _isInitialMaximize = true; private var _isInitialMaximize = true;
private val _maximizeProgress get() = _view?.progress ?: 0.0f; private val _maximizeProgress get() = _view?.progress ?: 0.0f;
@ -74,6 +86,29 @@ class VideoDetailFragment : MainFragment {
_viewDetail?.prevVideo(true); _viewDetail?.prevVideo(true);
} }
private fun onStateChanged(state: VideoDetailFragment.State) {
updateOrientation()
}
private fun updateOrientation() {
val isMaximized = state == State.MAXIMIZED
val isFullScreenPortraitAllowed = Settings.instance.playback.fullscreenPortrait;
val currentOrientation = _currentOrientation
val isFs = isFullscreen
if (isFs && isMaximized) {
if (isFullScreenPortraitAllowed) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
} else {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
}
} else {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
}
Log.i(TAG, "updateOrientation (isFs = ${isFs}, currentOrientation = ${currentOrientation}, isMaximized = ${isMaximized}, isFullScreenPortraitAllowed = ${isFullScreenPortraitAllowed}) resulted in requested orientation ${activity?.requestedOrientation}");
}
override fun onShownWithView(parameter: Any?, isBack: Boolean) { override fun onShownWithView(parameter: Any?, isBack: Boolean) {
super.onShownWithView(parameter, isBack); super.onShownWithView(parameter, isBack);
Logger.i(TAG, "onShownWithView parameter=$parameter") Logger.i(TAG, "onShownWithView parameter=$parameter")
@ -99,49 +134,6 @@ class VideoDetailFragment : MainFragment {
} }
} }
override fun onOrientationChanged(orientation: OrientationManager.Orientation) {
super.onOrientationChanged(orientation);
if(!_isActive || state != State.MAXIMIZED)
return;
var newOrientation = orientation;
val d = StateCasting.instance.activeDevice;
if (d != null && d.connectionState == CastConnectionState.CONNECTED) {
newOrientation = OrientationManager.Orientation.PORTRAIT;
} else if(StatePlayer.instance.rotationLock) {
return;
}
if(Settings.instance.other.bypassRotationPrevention && orientation == OrientationManager.Orientation.PORTRAIT)
changeOrientation(OrientationManager.Orientation.PORTRAIT);
if(lastOrientation == newOrientation)
return;
activity?.let {
if (isFullscreen) {
if (Settings.instance.playback.fullscreenPortrait) {
changeOrientation(newOrientation);
} else {
if(newOrientation == OrientationManager.Orientation.REVERSED_LANDSCAPE && it.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
changeOrientation(OrientationManager.Orientation.REVERSED_LANDSCAPE);
else if(newOrientation == OrientationManager.Orientation.LANDSCAPE && it.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE)
changeOrientation(OrientationManager.Orientation.LANDSCAPE);
else if(Settings.instance.playback.isAutoRotate() && (newOrientation == OrientationManager.Orientation.PORTRAIT || newOrientation == OrientationManager.Orientation.REVERSED_PORTRAIT)) {
_viewDetail?.setFullscreen(false);
}
}
}
else {
if(Settings.instance.playback.isAutoRotate() && (lastOrientation == OrientationManager.Orientation.PORTRAIT || lastOrientation == OrientationManager.Orientation.REVERSED_PORTRAIT)) {
lastOrientation = newOrientation;
_viewDetail?.setFullscreen(true);
}
}
}
lastOrientation = newOrientation;
}
override fun onBackPressed(): Boolean { override fun onBackPressed(): Boolean {
Logger.i(TAG, "onBackPressed") Logger.i(TAG, "onBackPressed")
@ -155,6 +147,7 @@ class VideoDetailFragment : MainFragment {
closeVideoDetails(); closeVideoDetails();
return true; return true;
} }
override fun onHide() { override fun onHide() {
super.onHide(); super.onHide();
} }
@ -266,7 +259,6 @@ class VideoDetailFragment : MainFragment {
override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) { } override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) { }
}); });
context
_view?.let { _view?.let {
if (it.progress >= 0.5 && it.progress < 1.0) if (it.progress >= 0.5 && it.progress < 1.0)
maximizeVideoDetail(); maximizeVideoDetail();
@ -274,9 +266,40 @@ class VideoDetailFragment : MainFragment {
minimizeVideoDetail(); minimizeVideoDetail();
} }
_loadUrlOnCreate?.let { _viewDetail?.setVideo(it.url, it.timeSeconds, it.playWhenReady) }; _autoRotateChangeListener = AutoRotateChangeListener(requireContext(), Handler()) { _ ->
updateOrientation()
}
_loadUrlOnCreate?.let { _viewDetail?.setVideo(it.url, it.timeSeconds, it.playWhenReady) };
maximizeVideoDetail(); maximizeVideoDetail();
SettingsActivity.settingsActivityClosed.subscribe(this) {
updateOrientation()
}
StatePlayer.instance.onRotationLockChanged.subscribe(this) {
updateOrientation()
}
_orientationListener = SimpleOrientationListener(requireActivity(), lifecycleScope)
_orientationListener.onOrientationChanged.subscribe {
_currentOrientation = it
Logger.i(TAG, "Current orientation changed (_currentOrientation = ${_currentOrientation})")
if (Settings.instance.playback.isAutoRotate()) {
if (!isFullscreen && (it == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || it == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE)) {
_viewDetail?.setFullscreen(true)
return@subscribe
}
if (isFullscreen && !Settings.instance.playback.fullscreenPortrait && (it == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || it == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT)) {
_viewDetail?.setFullscreen(false)
return@subscribe
}
}
updateOrientation()
}
return _view!!; return _view!!;
} }
@ -334,11 +357,6 @@ class VideoDetailFragment : MainFragment {
} }
} }
val realOrientation = if(activity is MainActivity) (activity as MainActivity).orientation else lastOrientation;
Logger.i(TAG, "Real orientation on boot ${realOrientation}, lastOrientation: ${lastOrientation}");
if(realOrientation != lastOrientation)
onOrientationChanged(realOrientation);
StateCasting.instance.onResume(); StateCasting.instance.onResume();
} }
override fun onPause() { override fun onPause() {
@ -380,6 +398,12 @@ class VideoDetailFragment : MainFragment {
override fun onDestroyMainView() { override fun onDestroyMainView() {
super.onDestroyMainView(); super.onDestroyMainView();
Logger.v(TAG, "onDestroyMainView"); Logger.v(TAG, "onDestroyMainView");
_autoRotateChangeListener?.unregister()
_orientationListener.stopListening()
SettingsActivity.settingsActivityClosed.remove(this)
StatePlayer.instance.onRotationLockChanged.remove(this)
_viewDetail?.let { _viewDetail?.let {
_viewDetail = null; _viewDetail = null;
it.onDestroy(); it.onDestroy();
@ -387,13 +411,6 @@ class VideoDetailFragment : MainFragment {
_view = null; _view = null;
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
StateCasting.instance.onActiveDeviceConnectionStateChanged.subscribe(this) { _, _ ->
onOrientationChanged(lastOrientation);
};
}
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
@ -409,64 +426,38 @@ class VideoDetailFragment : MainFragment {
onMaximized.clear(); onMaximized.clear();
} }
private fun hideSystemUI() {
WindowCompat.setDecorFitsSystemWindows(requireActivity().window, false)
activity?.window?.insetsController?.let { controller ->
controller.hide(WindowInsets.Type.statusBars())
controller.hide(WindowInsets.Type.systemBars())
controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
private fun showSystemUI() {
WindowCompat.setDecorFitsSystemWindows(requireActivity().window, true)
activity?.window?.insetsController?.let { controller ->
controller.show(WindowInsets.Type.statusBars())
controller.show(WindowInsets.Type.systemBars())
controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_DEFAULT
}
}
private fun onFullscreenChanged(fullscreen : Boolean) { private fun onFullscreenChanged(fullscreen : Boolean) {
activity?.let {
if (fullscreen) {
if (Settings.instance.playback.fullscreenPortrait) {
changeOrientation(lastOrientation);
} else {
var orient = lastOrientation;
if(orient == OrientationManager.Orientation.PORTRAIT || orient == OrientationManager.Orientation.REVERSED_PORTRAIT)
orient = OrientationManager.Orientation.LANDSCAPE;
changeOrientation(orient);
}
}
else
changeOrientation(OrientationManager.Orientation.PORTRAIT);
}
isFullscreen = fullscreen; isFullscreen = fullscreen;
onFullscreenChanged.emit(isFullscreen); onFullscreenChanged.emit(isFullscreen);
if (isFullscreen) {
hideSystemUI()
} else {
showSystemUI()
}
updateOrientation();
_view?.allowMotion = !fullscreen; _view?.allowMotion = !fullscreen;
} }
private fun changeOrientation(orientation: OrientationManager.Orientation) {
Logger.i(TAG, "Orientation Change:" + orientation.name);
activity?.let {
when (orientation) {
OrientationManager.Orientation.LANDSCAPE -> {
it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
_view?.allowMotion = false;
WindowCompat.setDecorFitsSystemWindows(requireActivity().window, false)
WindowInsetsControllerCompat(it.window, _viewDetail!!).let { controller ->
controller.hide(WindowInsetsCompat.Type.statusBars());
controller.hide(WindowInsetsCompat.Type.systemBars());
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
}
}
OrientationManager.Orientation.REVERSED_LANDSCAPE -> {
it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
_view?.allowMotion = false;
WindowCompat.setDecorFitsSystemWindows(requireActivity().window, false)
WindowInsetsControllerCompat(it.window, _viewDetail!!).let { controller ->
controller.hide(WindowInsetsCompat.Type.statusBars());
controller.hide(WindowInsetsCompat.Type.systemBars());
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
}
}
else -> {
it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
_view?.allowMotion = true;
WindowCompat.setDecorFitsSystemWindows(it.window, true)
WindowInsetsControllerCompat(it.window, _viewDetail!!).let { controller ->
controller.show(WindowInsetsCompat.Type.statusBars());
controller.show(WindowInsetsCompat.Type.systemBars())
}
}
}
}
}
companion object { companion object {
private val TAG = "VideoDetailFragment"; private val TAG = "VideoDetailFragment";

View file

@ -0,0 +1,42 @@
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
}
}

View file

@ -1,56 +0,0 @@
package com.futo.platformplayer.listeners
import android.content.Context
import android.view.OrientationEventListener
import com.futo.platformplayer.Settings
import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.logging.Logger
class OrientationManager : OrientationEventListener {
val onOrientationChanged = Event1<Orientation>();
var orientation : Orientation = Orientation.PORTRAIT;
constructor(context: Context) : super(context) { }
//TODO: Something weird is going on here
//TODO: Old implementation felt pretty good for me, but now with 0 deadzone still feels bad, even though code should be identical?
override fun onOrientationChanged(orientationAnglep: Int) {
if (orientationAnglep == -1) return
val deadZone = Settings.instance.playback.getAutoRotateDeadZoneDegrees()
val isInDeadZone = when (orientation) {
Orientation.PORTRAIT -> orientationAnglep in 0 until (60 - deadZone) || orientationAnglep in (300 + deadZone) .. 360
Orientation.REVERSED_LANDSCAPE -> orientationAnglep in (60 + deadZone) until (140 - deadZone)
Orientation.REVERSED_PORTRAIT -> orientationAnglep in (140 + deadZone) until (220 - deadZone)
Orientation.LANDSCAPE -> orientationAnglep in (220 + deadZone) until (300 - deadZone)
}
if (isInDeadZone) {
return;
}
val newOrientation = when (orientationAnglep) {
in 60 until 140 -> Orientation.REVERSED_LANDSCAPE
in 140 until 220 -> Orientation.REVERSED_PORTRAIT
in 220 until 300 -> Orientation.LANDSCAPE
else -> Orientation.PORTRAIT
}
Logger.i("OrientationManager", "Orientation=$newOrientation orientationAnglep=$orientationAnglep");
if (newOrientation != orientation) {
orientation = newOrientation
onOrientationChanged.emit(newOrientation)
}
}
//TODO: Perhaps just use ActivityInfo orientations instead..
enum class Orientation {
PORTRAIT,
LANDSCAPE,
REVERSED_PORTRAIT,
REVERSED_LANDSCAPE
}
}

View file

@ -120,7 +120,9 @@ class MediaPlaybackService : Service() {
override fun onStop() { override fun onStop() {
super.onStop(); super.onStop();
Logger.i(TAG, "Media session callback onStop()"); Logger.i(TAG, "Media session callback onStop()");
MediaControlReceiver.onCloseReceived.emit(); //MediaControlReceiver.onCloseReceived.emit();
MediaControlReceiver.onPauseReceived.emit();
updateMediaSession( null);
} }
override fun onSkipToPrevious() { override fun onSkipToPrevious() {

View file

@ -38,7 +38,13 @@ class StatePlayer {
private var _thumbnailExoPlayer : PlayerManager? = null; private var _thumbnailExoPlayer : PlayerManager? = null;
//Video Status //Video Status
var rotationLock : Boolean = false; var rotationLock: Boolean = false
get() = field
set(value) {
field = value
onRotationLockChanged.emit(value)
}
val onRotationLockChanged = Event1<Boolean>()
var loopVideo : Boolean = false; var loopVideo : Boolean = false;
val isPlaying: Boolean get() = _exoplayer?.player?.playWhenReady ?: false; val isPlaying: Boolean get() = _exoplayer?.player?.playWhenReady ?: false;

View file

@ -567,6 +567,8 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
fun setFullScreen(fullScreen: Boolean) { fun setFullScreen(fullScreen: Boolean) {
updateRotateLock()
if (isFullScreen == fullScreen) { if (isFullScreen == fullScreen) {
return; return;
} }
@ -759,7 +761,7 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
} }
fun updateRotateLock() { fun updateRotateLock() {
if(!Settings.instance.playback.isAutoRotate()) { if(Settings.instance.playback.autoRotate == 0) {
_control_rotate_lock.visibility = View.GONE; _control_rotate_lock.visibility = View.GONE;
_control_rotate_lock_fullscreen.visibility = View.GONE; _control_rotate_lock_fullscreen.visibility = View.GONE;
} }

View file

@ -774,6 +774,8 @@
<string name="zoom">Zoom</string> <string name="zoom">Zoom</string>
<string name="check_to_see_if_an_update_is_available">Check to see if an update is available.</string> <string name="check_to_see_if_an_update_is_available">Check to see if an update is available.</string>
<string name="scroll_to_top">Scroll to top</string> <string name="scroll_to_top">Scroll to top</string>
<string name="disable_battery_optimization">Disable Battery Optimization</string>
<string name="click_to_go_to_battery_optimization_settings_disabling_battery_optimization_will_prevent_the_os_from_killing_media_sessions">Click to go to battery optimization settings. Disabling battery optimization will prevent the OS from killing media sessions.</string>
<string-array name="home_screen_array"> <string-array name="home_screen_array">
<item>Recommendations</item> <item>Recommendations</item>
<item>Subscriptions</item> <item>Subscriptions</item>

@ -1 +1 @@
Subproject commit 4ce7591688cc4ebd4dd1f60eaebd5a8fe3aa66ad Subproject commit 91639d939738d9cc81ebdb1cd047ead9edd3a5e8

View file

@ -3,6 +3,7 @@ pluginManagement {
gradlePluginPortal() gradlePluginPortal()
google() google()
mavenCentral() mavenCentral()
jcenter()
} }
} }
dependencyResolutionManagement { dependencyResolutionManagement {
@ -10,6 +11,7 @@ dependencyResolutionManagement {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
jcenter()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
} }
} }