feat: fullscreen compatibility mode
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
~~什么我居然开始写更新日志了~~
|
~~什么我居然开始写更新日志了~~
|
||||||
|
|
||||||
|
## 0.2.8
|
||||||
|
|
||||||
|
- 新增: 全屏兼容模式
|
||||||
|
|
||||||
## 0.2.7
|
## 0.2.7
|
||||||
|
|
||||||
- 新增: 日志框隐藏
|
- 新增: 日志框隐藏
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ android {
|
|||||||
applicationId = "io.github.miuzarte.scrcpyforandroid"
|
applicationId = "io.github.miuzarte.scrcpyforandroid"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 37
|
targetSdk = 37
|
||||||
versionCode = 23
|
versionCode = 24
|
||||||
versionName = "0.2.7"
|
versionName = "0.2.8"
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ internal fun DeviceTabScreen(
|
|||||||
bottomInnerPadding: Dp,
|
bottomInnerPadding: Dp,
|
||||||
onOpenReorderDevices: () -> Unit,
|
onOpenReorderDevices: () -> Unit,
|
||||||
onPreviewGestureLockChanged: (Boolean) -> Unit = {},
|
onPreviewGestureLockChanged: (Boolean) -> Unit = {},
|
||||||
|
onOpenFullscreenCompat: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val navigator = LocalRootNavigator.current
|
val navigator = LocalRootNavigator.current
|
||||||
var showThreePointMenu by rememberSaveable { mutableStateOf(false) }
|
var showThreePointMenu by rememberSaveable { mutableStateOf(false) }
|
||||||
@@ -249,6 +250,7 @@ internal fun DeviceTabScreen(
|
|||||||
bottomInnerPadding = bottomInnerPadding,
|
bottomInnerPadding = bottomInnerPadding,
|
||||||
twoPaneSideToggleRequest = twoPaneSideToggleRequest,
|
twoPaneSideToggleRequest = twoPaneSideToggleRequest,
|
||||||
onPreviewGestureLockChanged = onPreviewGestureLockChanged,
|
onPreviewGestureLockChanged = onPreviewGestureLockChanged,
|
||||||
|
onOpenFullscreenCompat = onOpenFullscreenCompat,
|
||||||
onCompactTopAppBarChanged = ::setTopAppBarCompact,
|
onCompactTopAppBarChanged = ::setTopAppBarCompact,
|
||||||
onTwoPaneSideActionChanged = ::setTwoPaneSideAction,
|
onTwoPaneSideActionChanged = ::setTwoPaneSideAction,
|
||||||
)
|
)
|
||||||
@@ -266,6 +268,7 @@ internal fun DeviceTabPage(
|
|||||||
bottomInnerPadding: Dp,
|
bottomInnerPadding: Dp,
|
||||||
twoPaneSideToggleRequest: Int = 0,
|
twoPaneSideToggleRequest: Int = 0,
|
||||||
onPreviewGestureLockChanged: (Boolean) -> Unit = {},
|
onPreviewGestureLockChanged: (Boolean) -> Unit = {},
|
||||||
|
onOpenFullscreenCompat: () -> Unit = {},
|
||||||
onCompactTopAppBarChanged: (Boolean) -> Unit = {},
|
onCompactTopAppBarChanged: (Boolean) -> Unit = {},
|
||||||
onTwoPaneSideActionChanged: (Boolean, Boolean) -> Unit = { _, _ -> },
|
onTwoPaneSideActionChanged: (Boolean, Boolean) -> Unit = { _, _ -> },
|
||||||
) {
|
) {
|
||||||
@@ -738,6 +741,14 @@ internal fun DeviceTabPage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun openFullscreenControl() {
|
||||||
|
if (asBundle.fullscreenCompatibilityMode) {
|
||||||
|
onOpenFullscreenCompat()
|
||||||
|
} else {
|
||||||
|
context.startActivity(StreamActivity.createIntent(context))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun startScrcpySession(
|
suspend fun startScrcpySession(
|
||||||
openFullscreen: Boolean = false,
|
openFullscreen: Boolean = false,
|
||||||
startAppOverride: String? = null,
|
startAppOverride: String? = null,
|
||||||
@@ -768,7 +779,7 @@ internal fun DeviceTabPage(
|
|||||||
resolvedOptions.video &&
|
resolvedOptions.video &&
|
||||||
resolvedOptions.videoPlayback
|
resolvedOptions.videoPlayback
|
||||||
) withContext(Dispatchers.Main) {
|
) withContext(Dispatchers.Main) {
|
||||||
context.startActivity(StreamActivity.createIntent(context))
|
openFullscreenControl()
|
||||||
}
|
}
|
||||||
if (resolvedOptions.disableScreensaver)
|
if (resolvedOptions.disableScreensaver)
|
||||||
AppScreenOn.acquire()
|
AppScreenOn.acquire()
|
||||||
@@ -1201,9 +1212,7 @@ internal fun DeviceTabPage(
|
|||||||
sessionInfo = sessionInfo,
|
sessionInfo = sessionInfo,
|
||||||
onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) },
|
onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) },
|
||||||
showFullscreenAction = false,
|
showFullscreenAction = false,
|
||||||
onOpenFullscreen = {
|
onOpenFullscreen = ::openFullscreenControl,
|
||||||
context.startActivity(StreamActivity.createIntent(context))
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1216,9 +1225,7 @@ internal fun DeviceTabPage(
|
|||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
sessionInfo = sessionInfo,
|
sessionInfo = sessionInfo,
|
||||||
previewHeightDp = asBundle.devicePreviewCardHeightDp.coerceAtLeast(120),
|
previewHeightDp = asBundle.devicePreviewCardHeightDp.coerceAtLeast(120),
|
||||||
onOpenFullscreen = {
|
onOpenFullscreen = ::openFullscreenControl,
|
||||||
context.startActivity(StreamActivity.createIntent(context))
|
|
||||||
},
|
|
||||||
directControlEnabled = directControlEnabled,
|
directControlEnabled = directControlEnabled,
|
||||||
onInjectTouch = { action, pointerId, x, y, pressure, actionButton, buttons ->
|
onInjectTouch = { action, pointerId, x, y, pressure, actionButton, buttons ->
|
||||||
val session = sessionInfo
|
val session = sessionInfo
|
||||||
@@ -1319,9 +1326,7 @@ internal fun DeviceTabPage(
|
|||||||
sessionInfo = sessionInfo,
|
sessionInfo = sessionInfo,
|
||||||
onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) },
|
onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) },
|
||||||
showFullscreenAction = canShowPreviewControls,
|
showFullscreenAction = canShowPreviewControls,
|
||||||
onOpenFullscreen = {
|
onOpenFullscreen = ::openFullscreenControl,
|
||||||
context.startActivity(StreamActivity.createIntent(context))
|
|
||||||
},
|
|
||||||
reverseSideActions = asBundle.deviceTwoPaneConfigOnRight,
|
reverseSideActions = asBundle.deviceTwoPaneConfigOnRight,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package io.github.miuzarte.scrcpyforandroid.pages
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
@@ -50,6 +51,9 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
import androidx.navigation3.runtime.NavKey
|
import androidx.navigation3.runtime.NavKey
|
||||||
import androidx.navigation3.runtime.entryProvider
|
import androidx.navigation3.runtime.entryProvider
|
||||||
import androidx.navigation3.runtime.rememberDecoratedNavEntries
|
import androidx.navigation3.runtime.rememberDecoratedNavEntries
|
||||||
@@ -149,6 +153,7 @@ sealed interface RootScreen : NavKey {
|
|||||||
data object Advanced : RootScreen
|
data object Advanced : RootScreen
|
||||||
data object About : RootScreen
|
data object About : RootScreen
|
||||||
data object VirtualButtonOrder : RootScreen
|
data object VirtualButtonOrder : RootScreen
|
||||||
|
data object FullscreenControl : RootScreen // compatibility mode
|
||||||
data class ScrcpyOptionRecord(val profileId: String) : RootScreen
|
data class ScrcpyOptionRecord(val profileId: String) : RootScreen
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,8 +389,10 @@ fun MainScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Derived flags
|
// Derived flags
|
||||||
val canNavigateBack = rootBackStack.size > 1
|
val isFullscreenControlRoute = currentRootScreen is RootScreen.FullscreenControl
|
||||||
|| selectedTabIndex != MainBottomTabDestination.Devices.ordinal
|
val canNavigateBack = !isFullscreenControlRoute &&
|
||||||
|
(rootBackStack.size > 1
|
||||||
|
|| selectedTabIndex != MainBottomTabDestination.Devices.ordinal)
|
||||||
|
|
||||||
fun navigateToTab(tab: MainBottomTabDestination) {
|
fun navigateToTab(tab: MainBottomTabDestination) {
|
||||||
val targetIndex = tab.ordinal
|
val targetIndex = tab.ordinal
|
||||||
@@ -574,6 +581,9 @@ fun MainScreen() {
|
|||||||
onPreviewGestureLockChanged = { locked ->
|
onPreviewGestureLockChanged = { locked ->
|
||||||
devicePreviewGestureLock = locked
|
devicePreviewGestureLock = locked
|
||||||
},
|
},
|
||||||
|
onOpenFullscreenCompat = {
|
||||||
|
rootNavigator.push(RootScreen.FullscreenControl)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
MainBottomTabDestination.Terminal -> TerminalScreen(
|
MainBottomTabDestination.Terminal -> TerminalScreen(
|
||||||
@@ -667,6 +677,49 @@ fun MainScreen() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entry(RootScreen.FullscreenControl) {
|
||||||
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
LaunchedEffect(currentSession) {
|
||||||
|
if (currentSession == null) rootNavigator.pop()
|
||||||
|
}
|
||||||
|
DisposableEffect(lifecycleOwner) {
|
||||||
|
val observer = LifecycleEventObserver { _, event ->
|
||||||
|
if (event == Lifecycle.Event.ON_STOP) {
|
||||||
|
rootNavigator.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lifecycleOwner.lifecycle.addObserver(observer)
|
||||||
|
onDispose {
|
||||||
|
lifecycleOwner.lifecycle.removeObserver(observer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DisposableEffect(activity) {
|
||||||
|
onDispose {
|
||||||
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FullscreenControlScreen(
|
||||||
|
scrcpy = scrcpy,
|
||||||
|
onBack = rootNavigator.pop,
|
||||||
|
isInPip = false,
|
||||||
|
onVideoSizeChanged = { width, height ->
|
||||||
|
activity?.requestedOrientation =
|
||||||
|
if (width >= height) {
|
||||||
|
if (asBundle.fullscreenControlIgnoreSystemRotationLock)
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
||||||
|
else
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||||
|
} else {
|
||||||
|
if (asBundle.fullscreenControlIgnoreSystemRotationLock)
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
|
||||||
|
else
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onVideoBoundsInWindowChanged = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
entry<RootScreen.ScrcpyOptionRecord> { route ->
|
entry<RootScreen.ScrcpyOptionRecord> { route ->
|
||||||
RecordPreferencesScreen(
|
RecordPreferencesScreen(
|
||||||
scrollBehavior = advancedPageScrollBehavior,
|
scrollBehavior = advancedPageScrollBehavior,
|
||||||
@@ -674,7 +727,6 @@ fun MainScreen() {
|
|||||||
scrcpy = scrcpy,
|
scrcpy = scrcpy,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val rootEntries = rememberDecoratedNavEntries(
|
val rootEntries = rememberDecoratedNavEntries(
|
||||||
|
|||||||
@@ -631,6 +631,16 @@ fun SettingsPage(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SwitchPreference(
|
||||||
|
title = "全屏兼容模式",
|
||||||
|
summary = "启用后全屏控制页不再跨 Activity,会导致画中画不可用",
|
||||||
|
checked = asBundle.fullscreenCompatibilityMode,
|
||||||
|
onCheckedChange = {
|
||||||
|
asBundle = asBundle.copy(
|
||||||
|
fullscreenCompatibilityMode = it
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
intPreferencesKey("fullscreen_floating_button_ring_alpha_percent"),
|
intPreferencesKey("fullscreen_floating_button_ring_alpha_percent"),
|
||||||
100,
|
100,
|
||||||
)
|
)
|
||||||
|
val FULLSCREEN_COMPATIBILITY_MODE = Pair(
|
||||||
|
booleanPreferencesKey("fullscreen_compatibility_mode"),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
val FULLSCREEN_FLOATING_BUTTON_X_FRACTION = Pair(
|
val FULLSCREEN_FLOATING_BUTTON_X_FRACTION = Pair(
|
||||||
floatPreferencesKey("fullscreen_floating_button_x_fraction"),
|
floatPreferencesKey("fullscreen_floating_button_x_fraction"),
|
||||||
@@ -304,6 +308,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
val fullscreenFloatingButtonSizeDp: Int,
|
val fullscreenFloatingButtonSizeDp: Int,
|
||||||
val fullscreenFloatingButtonBackgroundAlphaPercent: Int,
|
val fullscreenFloatingButtonBackgroundAlphaPercent: Int,
|
||||||
val fullscreenFloatingButtonRingAlphaPercent: Int,
|
val fullscreenFloatingButtonRingAlphaPercent: Int,
|
||||||
|
val fullscreenCompatibilityMode: Boolean,
|
||||||
|
|
||||||
val fullscreenFloatingButtonXFraction: Float,
|
val fullscreenFloatingButtonXFraction: Float,
|
||||||
val fullscreenFloatingButtonYFraction: Float,
|
val fullscreenFloatingButtonYFraction: Float,
|
||||||
@@ -366,6 +371,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
bundleField(FULLSCREEN_FLOATING_BUTTON_SIZE_DP) { it.fullscreenFloatingButtonSizeDp },
|
bundleField(FULLSCREEN_FLOATING_BUTTON_SIZE_DP) { it.fullscreenFloatingButtonSizeDp },
|
||||||
bundleField(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT) { it.fullscreenFloatingButtonBackgroundAlphaPercent },
|
bundleField(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT) { it.fullscreenFloatingButtonBackgroundAlphaPercent },
|
||||||
bundleField(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT) { it.fullscreenFloatingButtonRingAlphaPercent },
|
bundleField(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT) { it.fullscreenFloatingButtonRingAlphaPercent },
|
||||||
|
bundleField(FULLSCREEN_COMPATIBILITY_MODE) { it.fullscreenCompatibilityMode },
|
||||||
|
|
||||||
bundleField(FULLSCREEN_FLOATING_BUTTON_X_FRACTION) { it.fullscreenFloatingButtonXFraction },
|
bundleField(FULLSCREEN_FLOATING_BUTTON_X_FRACTION) { it.fullscreenFloatingButtonXFraction },
|
||||||
bundleField(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION) { it.fullscreenFloatingButtonYFraction },
|
bundleField(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION) { it.fullscreenFloatingButtonYFraction },
|
||||||
@@ -432,6 +438,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
preferences.read(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT),
|
preferences.read(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT),
|
||||||
fullscreenFloatingButtonRingAlphaPercent =
|
fullscreenFloatingButtonRingAlphaPercent =
|
||||||
preferences.read(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT),
|
preferences.read(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT),
|
||||||
|
fullscreenCompatibilityMode = preferences.read(FULLSCREEN_COMPATIBILITY_MODE),
|
||||||
|
|
||||||
fullscreenFloatingButtonXFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_X_FRACTION),
|
fullscreenFloatingButtonXFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_X_FRACTION),
|
||||||
fullscreenFloatingButtonYFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION),
|
fullscreenFloatingButtonYFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION),
|
||||||
|
|||||||
Reference in New Issue
Block a user