Refactor and split up extensions (#270)

This commit is contained in:
Max Rumpf
2020-12-13 15:43:46 +01:00
committed by GitHub
parent ef4eaf8b2f
commit 122448fadf
7 changed files with 87 additions and 82 deletions
@@ -8,7 +8,6 @@ import android.os.Bundle
import android.os.IBinder
import android.view.OrientationEventListener
import androidx.appcompat.app.AppCompatActivity
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@@ -17,7 +16,10 @@ import org.jellyfin.mobile.cast.IChromecast
import org.jellyfin.mobile.fragment.ConnectFragment
import org.jellyfin.mobile.fragment.WebViewFragment
import org.jellyfin.mobile.player.PlayerFragment
import org.jellyfin.mobile.utils.*
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.PermissionRequestHelper
import org.jellyfin.mobile.utils.SmartOrientationListener
import org.jellyfin.mobile.utils.replaceFragment
import org.jellyfin.mobile.viewmodel.MainViewModel
import org.jellyfin.mobile.viewmodel.ServerState
import org.jellyfin.mobile.webapp.RemotePlayerService
@@ -31,8 +33,6 @@ class MainActivity : AppCompatActivity() {
val chromecast: IChromecast = Chromecast()
private val permissionRequestHelper: PermissionRequestHelper by inject()
val rootView: CoordinatorLayout by lazyView(R.id.root_view)
var serviceBinder: RemotePlayerService.ServiceBinder? = null
private set
private val serviceConnection: ServiceConnection = object : ServiceConnection {
@@ -91,10 +91,10 @@ class WebViewFragment : Fragment() {
// offsetting 100dp from the center in both directions
// uses the maximum available space
val verticalCenter = webView.measuredHeight / 2
val offset = webView.context.dip(100)
val offset = webView.resources.dip(100)
// Arbitrary, currently 2x minimum touch target size
val exclusionWidth = webView.context.dip(96)
val exclusionWidth = webView.resources.dip(96)
webView.systemGestureExclusionRects = listOf(
Rect(
@@ -282,7 +282,7 @@ class PlayerFragment : Fragment() {
return false
// Check whether swipe was started in excluded region
if (firstEvent.y < GESTURE_EXCLUSION_AREA_TOP * resources.displayMetrics.density)
if (firstEvent.y < resources.dip(GESTURE_EXCLUSION_AREA_TOP))
return false
// Check whether swipe was oriented vertically
@@ -0,0 +1,47 @@
@file:Suppress("DEPRECATION")
package org.jellyfin.mobile.utils
import android.app.Activity
import android.content.pm.ActivityInfo
import android.graphics.Point
import android.view.Surface
import android.view.View
import android.view.WindowManager
const val STABLE_LAYOUT_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
const val FULLSCREEN_FLAGS = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
fun Activity.isFullscreen() = window.decorView.systemUiVisibility.hasFlag(FULLSCREEN_FLAGS)
fun Activity.enableFullscreen() {
window.apply {
decorView.systemUiVisibility = FULLSCREEN_FLAGS
addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
}
}
fun Activity.disableFullscreen(keepStableLayout: Boolean = false) {
window.apply {
decorView.systemUiVisibility = if (keepStableLayout) STABLE_LAYOUT_FLAGS else 0
clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
}
fun Activity.lockOrientation() {
val display = windowManager.defaultDisplay
val size = Point().also(display::getSize)
val height = size.y
val width = size.x
requestedOrientation = when (display.rotation) {
Surface.ROTATION_90 -> if (width > height) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
Surface.ROTATION_180 -> if (height > width) ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
Surface.ROTATION_270 -> if (width > height) ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
else -> if (height > width) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
}
@@ -0,0 +1,24 @@
@file:Suppress("NOTHING_TO_INLINE")
package org.jellyfin.mobile.utils
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.add
import androidx.fragment.app.replace
import org.jellyfin.mobile.MainActivity
import org.jellyfin.mobile.R
inline fun <reified T : Fragment> FragmentManager.addFragment() {
beginTransaction().apply {
add<T>(R.id.fragment_container)
addToBackStack(null)
}.commit()
}
inline fun <reified T : Fragment> FragmentManager.replaceFragment(args: Bundle? = null) {
beginTransaction().replace<T>(R.id.fragment_container, args = args).commit()
}
inline fun Fragment.requireMainActivity(): MainActivity = requireActivity() as MainActivity
@@ -33,8 +33,7 @@ fun MainActivity.requestNoBatteryOptimizations() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val powerManager: PowerManager = getSystemService(AppCompatActivity.POWER_SERVICE) as PowerManager
if (!appPreferences.ignoreBatteryOptimizations && !powerManager.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID)) {
Snackbar.make(rootView, R.string.battery_optimizations_message, Snackbar.LENGTH_INDEFINITE).apply {
// Add action
Snackbar.make(findViewById(R.id.root_view), R.string.battery_optimizations_message, Snackbar.LENGTH_INDEFINITE).apply {
setAction(android.R.string.ok) {
try {
val intent = Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
@@ -46,7 +45,6 @@ fun MainActivity.requestNoBatteryOptimizations() {
// Ignore after the user interacted with the snackbar at least once
appPreferences.ignoreBatteryOptimizations = true
}
show()
}
}
@@ -1,75 +1,23 @@
@file:Suppress("NOTHING_TO_INLINE")
@file:Suppress("unused", "NOTHING_TO_INLINE")
package org.jellyfin.mobile.utils
import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.graphics.Point
import android.os.Bundle
import android.view.*
import android.content.res.Resources
import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import androidx.annotation.StyleRes
import androidx.core.view.ViewCompat
import androidx.core.view.updateMargins
import androidx.fragment.app.*
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.jellyfin.mobile.MainActivity
import org.jellyfin.mobile.R
inline fun <T : View> Activity.lazyView(@IdRes id: Int) =
lazy(LazyThreadSafetyMode.NONE) { findViewById<T>(id) }
@Suppress("DEPRECATION")
const val STABLE_LAYOUT_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
@Suppress("DEPRECATION")
const val FULLSCREEN_FLAGS = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
@Suppress("DEPRECATION")
fun Activity.isFullscreen() = window.decorView.systemUiVisibility.hasFlag(FULLSCREEN_FLAGS)
@Suppress("DEPRECATION")
fun Activity.enableFullscreen() {
window.apply {
decorView.systemUiVisibility = FULLSCREEN_FLAGS
addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
}
}
@Suppress("DEPRECATION")
fun Activity.disableFullscreen(keepStableLayout: Boolean = false) {
window.apply {
decorView.systemUiVisibility = if (keepStableLayout) STABLE_LAYOUT_FLAGS else 0
clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
}
@Suppress("DEPRECATION")
fun Activity.lockOrientation() {
val display = windowManager.defaultDisplay
val size = Point().also(display::getSize)
val height = size.y
val width = size.x
requestedOrientation = when (display.rotation) {
Surface.ROTATION_90 -> if (width > height) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
Surface.ROTATION_180 -> if (height > width) ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
Surface.ROTATION_270 -> if (width > height) ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
else -> if (height > width) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
}
inline fun Context.dip(px: Int) = (px * resources.displayMetrics.density).toInt()
inline fun Context.toast(@StringRes text: Int, duration: Int = Toast.LENGTH_SHORT) =
Toast.makeText(this, text, duration).show()
@@ -81,24 +29,10 @@ inline fun LifecycleOwner.runOnUiThread(noinline block: suspend CoroutineScope.(
lifecycleScope.launch(Dispatchers.Main, block = block)
}
inline fun <reified T : Fragment> FragmentManager.addFragment() {
beginTransaction().apply {
add<T>(R.id.fragment_container)
addToBackStack(null)
}.commit()
}
inline fun <reified T : Fragment> FragmentManager.replaceFragment(args: Bundle? = null) {
beginTransaction().replace<T>(R.id.fragment_container, args = args).commit()
}
fun LayoutInflater.withThemedContext(context: Context, @StyleRes style: Int): LayoutInflater {
return cloneInContext(ContextThemeWrapper(context, style))
}
@Suppress("NOTHING_TO_INLINE")
inline fun Fragment.requireMainActivity(): MainActivity = requireActivity() as MainActivity
fun View.applyWindowInsetsAsMargins() {
ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
val layoutParams = layoutParams as ViewGroup.MarginLayoutParams
@@ -111,3 +45,5 @@ fun View.applyWindowInsetsAsMargins() {
insets
}
}
inline fun Resources.dip(px: Int) = (px * displayMetrics.density).toInt()