refactor: impl more scrcpy options; remove unused class/constants
- 移除不再需要的 `AppDefaults` 与 `AppPreferenceKeys` - 实现了 `--show-touches`, `--no-power-on`, `--power-off-on-close`, `--disable-screensaver`, `--screen-off-timeout=seconds`, `--require-audio`, `--no-vd-destroy-content`, `--no-vd-system-decorations`
This commit is contained in:
@@ -1,82 +0,0 @@
|
||||
package io.github.miuzarte.scrcpyforandroid.constants
|
||||
|
||||
object AppDefaults {
|
||||
const val EVENT_LOG_LINES = 512
|
||||
const val ADB_PORT = 5555
|
||||
|
||||
// Devices
|
||||
const val QUICK_CONNECT_INPUT = ""
|
||||
|
||||
const val PAIR_HOST = ""
|
||||
const val PAIR_PORT = ""
|
||||
const val PAIR_CODE = ""
|
||||
|
||||
const val AUDIO_ENABLED = true
|
||||
const val AUDIO_CODEC = "opus"
|
||||
const val AUDIO_BIT_RATE_KBPS = 128
|
||||
const val AUDIO_BIT_RATE_INPUT = "128"
|
||||
const val VIDEO_CODEC = "h264"
|
||||
const val VIDEO_BIT_RATE_MBPS = 8f
|
||||
const val VIDEO_BIT_RATE_INPUT = "8.0"
|
||||
|
||||
const val TURN_SCREEN_OFF = false
|
||||
const val NO_CONTROL = false
|
||||
const val NO_VIDEO = false
|
||||
|
||||
const val VIDEO_SOURCE_PRESET = "display"
|
||||
const val DISPLAY_ID = ""
|
||||
|
||||
const val CAMERA_ID = ""
|
||||
const val CAMERA_FACING_PRESET = ""
|
||||
const val CAMERA_SIZE_PRESET = ""
|
||||
const val CAMERA_SIZE_CUSTOM = ""
|
||||
const val CAMERA_AR = ""
|
||||
const val CAMERA_FPS = ""
|
||||
const val CAMERA_HIGH_SPEED = false
|
||||
|
||||
const val AUDIO_SOURCE_PRESET = "output"
|
||||
const val AUDIO_SOURCE_CUSTOM = ""
|
||||
const val AUDIO_DUP = false
|
||||
const val NO_AUDIO_PLAYBACK = false
|
||||
const val REQUIRE_AUDIO = false
|
||||
|
||||
const val MAX_SIZE_INPUT = ""
|
||||
const val MAX_FPS_INPUT = ""
|
||||
|
||||
const val VIDEO_ENCODER = ""
|
||||
const val VIDEO_CODEC_OPTION = ""
|
||||
const val AUDIO_ENCODER = ""
|
||||
const val AUDIO_CODEC_OPTION = ""
|
||||
|
||||
const val NEW_DISPLAY_WIDTH = ""
|
||||
const val NEW_DISPLAY_HEIGHT = ""
|
||||
const val NEW_DISPLAY_DPI = ""
|
||||
|
||||
const val CROP_WIDTH = ""
|
||||
const val CROP_HEIGHT = ""
|
||||
const val CROP_X = ""
|
||||
const val CROP_Y = ""
|
||||
|
||||
// Settings
|
||||
const val THEME_BASE_INDEX = 0
|
||||
const val MONET = false
|
||||
|
||||
const val FULLSCREEN_DEBUG_INFO = false
|
||||
const val SHOW_FULLSCREEN_VIRTUAL_BUTTONS = true
|
||||
const val KEEP_SCREEN_ON_WHEN_STREAMING = false
|
||||
const val DEVICE_PREVIEW_CARD_HEIGHT_DP = 320
|
||||
const val PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT = true
|
||||
const val VIRTUAL_BUTTONS_LAYOUT =
|
||||
"more:1,app_switch:1,home:0,back:1,menu:0,notification:0,volume_up:0,volume_down:0,volume_mute:0,power:0,screenshot:0"
|
||||
|
||||
const val CUSTOM_SERVER_URI = ""
|
||||
|
||||
const val SERVER_REMOTE_PATH = "/data/local/tmp/scrcpy-server.jar"
|
||||
const val SERVER_REMOTE_PATH_INPUT = ""
|
||||
|
||||
const val ADB_KEY_NAME = "scrcpy"
|
||||
const val ADB_KEY_NAME_INPUT = ""
|
||||
const val ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN = true
|
||||
const val ADB_AUTO_RECONNECT_PAIRED_DEVICE = true
|
||||
const val ADB_MDNS_LAN_DISCOVERY = true
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package io.github.miuzarte.scrcpyforandroid.constants
|
||||
|
||||
object AppPreferenceKeys {
|
||||
const val PREFS_NAME = "scrcpy_app_prefs"
|
||||
|
||||
// Devices
|
||||
const val QUICK_DEVICES = "quick_devices"
|
||||
const val QUICK_CONNECT_INPUT = "quick_connect_input"
|
||||
|
||||
const val PAIR_HOST = "pair_host"
|
||||
const val PAIR_PORT = "pair_port"
|
||||
const val PAIR_CODE = "pair_code"
|
||||
|
||||
const val AUDIO_ENABLED = "audio_enabled"
|
||||
const val AUDIO_CODEC = "audio_codec"
|
||||
const val AUDIO_BIT_RATE_INPUT = "audio_bit_rate_input"
|
||||
const val AUDIO_BIT_RATE_KBPS = "audio_bit_rate_kbps"
|
||||
const val VIDEO_CODEC = "video_codec"
|
||||
const val VIDEO_BIT_RATE_MBPS = "video_bit_rate_mbps"
|
||||
const val VIDEO_BIT_RATE_INPUT = "video_bit_rate_input"
|
||||
|
||||
const val TURN_SCREEN_OFF = "turn_screen_off"
|
||||
const val NO_CONTROL = "no_control"
|
||||
const val NO_VIDEO = "no_video"
|
||||
|
||||
const val VIDEO_SOURCE_PRESET = "video_source_preset"
|
||||
const val DISPLAY_ID = "display_id"
|
||||
|
||||
const val CAMERA_ID = "camera_id"
|
||||
const val CAMERA_FACING_PRESET = "camera_facing_preset"
|
||||
const val CAMERA_SIZE_PRESET = "camera_size_preset"
|
||||
const val CAMERA_SIZE_CUSTOM = "camera_size_custom"
|
||||
const val CAMERA_AR = "camera_ar"
|
||||
const val CAMERA_FPS = "camera_fps"
|
||||
const val CAMERA_HIGH_SPEED = "camera_high_speed"
|
||||
|
||||
const val AUDIO_SOURCE_PRESET = "audio_source_preset"
|
||||
const val AUDIO_SOURCE_CUSTOM = "audio_source_custom"
|
||||
const val AUDIO_DUP = "audio_dup"
|
||||
const val NO_AUDIO_PLAYBACK = "no_audio_playback"
|
||||
const val REQUIRE_AUDIO = "require_audio"
|
||||
|
||||
const val MAX_SIZE_INPUT = "max_size_input"
|
||||
const val MAX_FPS_INPUT = "max_fps_input"
|
||||
|
||||
const val VIDEO_ENCODER = "video_encoder"
|
||||
const val VIDEO_CODEC_OPTION = "video_codec_options"
|
||||
const val AUDIO_ENCODER = "audio_encoder"
|
||||
const val AUDIO_CODEC_OPTION = "audio_codec_options"
|
||||
|
||||
const val NEW_DISPLAY_WIDTH = "new_display_width"
|
||||
const val NEW_DISPLAY_HEIGHT = "new_display_height"
|
||||
const val NEW_DISPLAY_DPI = "new_display_dpi"
|
||||
|
||||
const val CROP_WIDTH = "crop_width"
|
||||
const val CROP_HEIGHT = "crop_height"
|
||||
const val CROP_X = "crop_x"
|
||||
const val CROP_Y = "crop_y"
|
||||
|
||||
// Settings
|
||||
const val THEME_BASE_INDEX = "theme_base_index"
|
||||
const val MONET = "monet"
|
||||
|
||||
const val FULLSCREEN_DEBUG_INFO = "fullscreen_debug_info"
|
||||
const val SHOW_FULLSCREEN_VIRTUAL_BUTTONS = "show_fullscreen_virtual_buttons"
|
||||
const val KEEP_SCREEN_ON_WHEN_STREAMING = "keep_screen_on_when_streaming"
|
||||
const val DEVICE_PREVIEW_CARD_HEIGHT_DP = "device_preview_card_height_dp"
|
||||
const val PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT = "preview_virtual_button_show_text"
|
||||
const val VIRTUAL_BUTTONS_LAYOUT = "virtual_buttons_layout"
|
||||
|
||||
const val CUSTOM_SERVER_URI = "custom_server_uri"
|
||||
|
||||
const val SERVER_REMOTE_PATH = "server_remote_path"
|
||||
|
||||
const val ADB_KEY_NAME = "adb_key_name"
|
||||
const val ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN = "adb_pairing_auto_discover_on_dialog_open"
|
||||
const val ADB_AUTO_RECONNECT_PAIRED_DEVICE = "adb_auto_reconnect_paired_device"
|
||||
const val ADB_MDNS_LAN_DISCOVERY = "adb_mdns_lan_discovery"
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.github.miuzarte.scrcpyforandroid.constants
|
||||
|
||||
object Defaults {
|
||||
const val EVENT_LOG_LINES = 512
|
||||
const val ADB_PORT = 5555;
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package io.github.miuzarte.scrcpyforandroid.pages
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.util.Log
|
||||
import android.view.WindowManager
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -22,6 +24,7 @@ import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import io.github.miuzarte.scrcpyforandroid.NativeCoreFacade
|
||||
import io.github.miuzarte.scrcpyforandroid.constants.Defaults
|
||||
@@ -92,7 +95,6 @@ fun DeviceTabScreen(
|
||||
snackbar: SnackbarController,
|
||||
scrollBehavior: ScrollBehavior,
|
||||
onOpenVirtualButtonOrder: () -> Unit,
|
||||
onSessionStartedChange: (Boolean) -> Unit,
|
||||
onOpenReorderDevices: () -> Unit,
|
||||
onOpenAdvancedPage: () -> Unit,
|
||||
onOpenFullscreenPage: (Scrcpy.Session.SessionInfo) -> Unit,
|
||||
@@ -142,7 +144,6 @@ fun DeviceTabScreen(
|
||||
scrcpy = scrcpy,
|
||||
snackbar = snackbar,
|
||||
scrollBehavior = scrollBehavior,
|
||||
onSessionStartedChange = onSessionStartedChange,
|
||||
onOpenAdvancedPage = onOpenAdvancedPage,
|
||||
onOpenFullscreenPage = onOpenFullscreenPage,
|
||||
)
|
||||
@@ -157,13 +158,14 @@ fun DeviceTabPage(
|
||||
scrcpy: Scrcpy,
|
||||
snackbar: SnackbarController,
|
||||
scrollBehavior: ScrollBehavior,
|
||||
onSessionStartedChange: (Boolean) -> Unit,
|
||||
onOpenAdvancedPage: () -> Unit,
|
||||
onOpenFullscreenPage: (Scrcpy.Session.SessionInfo) -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val taskScope = remember { CoroutineScope(Dispatchers.IO + SupervisorJob()) }
|
||||
val haptics = rememberAppHaptics()
|
||||
val activity = remember(context) { context as? Activity }
|
||||
|
||||
val asBundleShared by appSettings.bundleState.collectAsState()
|
||||
val asBundleSharedLatest by rememberUpdatedState(asBundleShared)
|
||||
@@ -214,6 +216,23 @@ fun DeviceTabPage(
|
||||
// read only
|
||||
val soBundleShared by scrcpyOptions.bundleState.collectAsState()
|
||||
|
||||
fun setKeepScreenOn(enabled: Boolean) {
|
||||
val window = activity?.window ?: return
|
||||
window.decorView.post {
|
||||
if (enabled) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(activity) {
|
||||
onDispose {
|
||||
setKeepScreenOn(false)
|
||||
}
|
||||
}
|
||||
|
||||
// Run adb operations on a dedicated single thread.
|
||||
// Try to avoid blocking UI/recomposition and keeps adb call ordering deterministic.
|
||||
|
||||
@@ -323,6 +342,7 @@ fun DeviceTabPage(
|
||||
) {
|
||||
// Also stops scrcpy.
|
||||
runCatching { scrcpy.stop() }
|
||||
setKeepScreenOn(false)
|
||||
runCatching { adbService.disconnect() }
|
||||
adbConnected = false
|
||||
currentTargetHost = ""
|
||||
@@ -706,7 +726,6 @@ fun DeviceTabPage(
|
||||
sessionInfoCodec = null
|
||||
sessionInfoControlEnabled = false
|
||||
}
|
||||
onSessionStartedChange(sessionInfo != null)
|
||||
}
|
||||
|
||||
fun sendVirtualButtonAction(action: VirtualButtonAction) {
|
||||
@@ -920,6 +939,9 @@ fun DeviceTabPage(
|
||||
runBusy("启动 scrcpy") {
|
||||
val options = scrcpyOptions.toClientOptions(soBundleShared).fix()
|
||||
val session = scrcpy.start(options)
|
||||
if (options.disableScreensaver) {
|
||||
setKeepScreenOn(true)
|
||||
}
|
||||
sessionInfo = session.copy(
|
||||
host = currentTargetHost,
|
||||
port = currentTargetPort
|
||||
@@ -949,6 +971,7 @@ fun DeviceTabPage(
|
||||
onStop = {
|
||||
runBusy("停止 scrcpy") {
|
||||
scrcpy.stop()
|
||||
setKeepScreenOn(false)
|
||||
sessionInfo = null
|
||||
statusLine = "${currentTarget!!.host}:${currentTarget.port}"
|
||||
logEvent("scrcpy 已停止")
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.net.Uri
|
||||
import android.os.SystemClock
|
||||
import android.view.WindowManager
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.PredictiveBackHandler
|
||||
@@ -266,27 +265,11 @@ fun MainScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
var sessionStarted by remember { mutableStateOf(false) }
|
||||
var showReorderDevices by rememberSaveable { mutableStateOf(false) }
|
||||
var fullscreenOrientation by rememberSaveable {
|
||||
mutableIntStateOf(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
|
||||
}
|
||||
|
||||
val keepScreenOnWhenStreamingEnabled = asBundle.keepScreenOnWhenStreaming
|
||||
// Keep-screen-on is controlled globally, so fullscreen and preview share the same behavior.
|
||||
DisposableEffect(activity, keepScreenOnWhenStreamingEnabled, sessionStarted) {
|
||||
val window = activity?.window
|
||||
val shouldKeepScreenOn = keepScreenOnWhenStreamingEnabled && sessionStarted
|
||||
if (window != null && shouldKeepScreenOn) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
onDispose {
|
||||
if (window != null && shouldKeepScreenOn) {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fullscreen route can force orientation based on stream ratio; all other routes are portrait.
|
||||
LaunchedEffect(activity, currentRootScreen, fullscreenOrientation) {
|
||||
val targetOrientation = when (currentRootScreen) {
|
||||
@@ -356,7 +339,6 @@ fun MainScreen() {
|
||||
snackbar = snackbarController,
|
||||
scrollBehavior = devicesPageScrollBehavior,
|
||||
onOpenVirtualButtonOrder = { rootBackStack.add(RootScreen.VirtualButtonOrder) },
|
||||
onSessionStartedChange = { sessionStarted = it },
|
||||
onOpenReorderDevices = { showReorderDevices = true },
|
||||
onOpenAdvancedPage = { rootBackStack.add(RootScreen.Advanced) },
|
||||
onOpenFullscreenPage = { session ->
|
||||
|
||||
@@ -264,14 +264,19 @@ internal fun ScrcpyAllOptionsPage(
|
||||
val videoEncoderDropdownItems = rememberSaveable(videoEncoders, listRefreshVersion) {
|
||||
listOf("") + videoEncoders
|
||||
}
|
||||
val videoEncoderIndex = rememberSaveable(soBundle.videoEncoder, videoEncoders, listRefreshVersion) {
|
||||
(videoEncoders.indexOf(soBundle.videoEncoder) + 1).coerceAtLeast(0)
|
||||
}
|
||||
val videoEncoderIndex =
|
||||
rememberSaveable(soBundle.videoEncoder, videoEncoders, listRefreshVersion) {
|
||||
(videoEncoders.indexOf(soBundle.videoEncoder) + 1).coerceAtLeast(0)
|
||||
}
|
||||
|
||||
val audioEncoderDropdownItems = rememberSaveable(audioEncoders, listRefreshVersion) {
|
||||
listOf("") + audioEncoders
|
||||
}
|
||||
val audioEncoderIndex = rememberSaveable(soBundle.audioEncoder, audioEncoders, listRefreshVersion) {
|
||||
val audioEncoderIndex = rememberSaveable(
|
||||
soBundle.audioEncoder,
|
||||
audioEncoders,
|
||||
listRefreshVersion
|
||||
) {
|
||||
(audioEncoders.indexOf(soBundle.audioEncoder) + 1).coerceAtLeast(0)
|
||||
}
|
||||
|
||||
@@ -419,6 +424,77 @@ internal fun ScrcpyAllOptionsPage(
|
||||
},
|
||||
// enabled = control || video,
|
||||
)
|
||||
SuperSlider(
|
||||
title = "投屏过程中受控机的息屏时间",
|
||||
summary = "--screen-off-timeout",
|
||||
value = soBundle.screenOffTimeout.coerceAtLeast(0).toFloat(),
|
||||
onValueChange = {
|
||||
soBundle = soBundle.copy(
|
||||
screenOffTimeout = it.roundToInt()
|
||||
.takeIf { value -> value > 0 }
|
||||
?.toLong() ?: -1
|
||||
)
|
||||
},
|
||||
valueRange = 0f..600f,
|
||||
steps = 600 - 1,
|
||||
unit = "s",
|
||||
zeroStateText = "默认",
|
||||
displayText =
|
||||
if (soBundle.screenOffTimeout <= 0) "默认"
|
||||
else soBundle.screenOffTimeout.toString(),
|
||||
inputInitialValue =
|
||||
if (soBundle.screenOffTimeout <= 0) ""
|
||||
else soBundle.screenOffTimeout.toString(),
|
||||
inputFilter = { it.filter(Char::isDigit) },
|
||||
inputValueRange = 0f..86400f,
|
||||
onInputConfirm = {
|
||||
soBundle = soBundle.copy(
|
||||
screenOffTimeout = it.toLongOrNull()
|
||||
?.takeIf { value -> value > 0 }
|
||||
?: -1
|
||||
)
|
||||
},
|
||||
)
|
||||
SuperSwitch(
|
||||
title = "开始投屏时不唤醒屏幕",
|
||||
summary = "--no-power-on",
|
||||
checked = !soBundle.powerOn,
|
||||
onCheckedChange = {
|
||||
soBundle = soBundle.copy(
|
||||
powerOn = !it
|
||||
)
|
||||
},
|
||||
)
|
||||
SuperSwitch(
|
||||
title = "结束投屏时息屏",
|
||||
summary = "--power-off-on-close",
|
||||
checked = soBundle.powerOffOnClose,
|
||||
onCheckedChange = {
|
||||
soBundle = soBundle.copy(
|
||||
powerOffOnClose = it
|
||||
)
|
||||
},
|
||||
)
|
||||
SuperSwitch(
|
||||
title = "显示物理触控",
|
||||
summary = "--show-touches",
|
||||
checked = soBundle.showTouches,
|
||||
onCheckedChange = {
|
||||
soBundle = soBundle.copy(
|
||||
showTouches = it
|
||||
)
|
||||
},
|
||||
)
|
||||
SuperSwitch(
|
||||
title = "投屏时保持本机屏幕唤醒",
|
||||
summary = "--disable-screensaver",
|
||||
checked = soBundle.disableScreensaver,
|
||||
onCheckedChange = {
|
||||
soBundle = soBundle.copy(
|
||||
disableScreensaver = it
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,6 +860,26 @@ internal fun ScrcpyAllOptionsPage(
|
||||
)
|
||||
},
|
||||
)
|
||||
SuperSwitch(
|
||||
title = "关闭虚拟显示器时保留内容",
|
||||
summary = "--no-vd-destroy-content",
|
||||
checked = !soBundle.vdDestroyContent,
|
||||
onCheckedChange = {
|
||||
soBundle = soBundle.copy(
|
||||
vdDestroyContent = !it
|
||||
)
|
||||
},
|
||||
)
|
||||
SuperSwitch(
|
||||
title = "禁用虚拟显示器系统装饰",
|
||||
summary = "--no-vd-system-decorations",
|
||||
checked = !soBundle.vdSystemDecorations,
|
||||
onCheckedChange = {
|
||||
soBundle = soBundle.copy(
|
||||
vdSystemDecorations = !it
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -194,14 +194,6 @@ fun SettingsPage(
|
||||
asBundle = asBundle.copy(fullscreenDebugInfo = it)
|
||||
},
|
||||
)
|
||||
SuperSwitch(
|
||||
title = "投屏时保持屏幕常亮",
|
||||
summary = "Scrcpy 启动后保持本机屏幕常亮,避免锁屏导致 ADB 断开",
|
||||
checked = asBundle.keepScreenOnWhenStreaming,
|
||||
onCheckedChange = {
|
||||
asBundle = asBundle.copy(keepScreenOnWhenStreaming = it)
|
||||
},
|
||||
)
|
||||
SuperSlider(
|
||||
title = "预览卡高度",
|
||||
summary = "设备页预览卡高度",
|
||||
|
||||
@@ -32,18 +32,16 @@ fun LazyColumn(
|
||||
content: LazyListScope.() -> Unit,
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
val focusClearModifier = if (clearFocusOnTap) {
|
||||
Modifier.pointerInput(Unit) {
|
||||
detectTapGestures(onTap = { focusManager.clearFocus() })
|
||||
}
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
||||
LazyColumn(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.then(focusClearModifier)
|
||||
.then(
|
||||
if (clearFocusOnTap)
|
||||
Modifier.pointerInput(Unit) {
|
||||
detectTapGestures(onTap = { focusManager.clearFocus() })
|
||||
} else Modifier
|
||||
)
|
||||
.overScrollVertical()
|
||||
.nestedScroll(scrollBehavior.nestedScrollConnection)
|
||||
.padding(contentPadding),
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -12,6 +13,8 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
||||
import top.yukonga.miuix.kmp.basic.Slider
|
||||
@@ -131,6 +134,10 @@ private fun SliderInputDialog(
|
||||
label = label,
|
||||
useLabelAsPlaceholder = useLabelAsPlaceholder,
|
||||
maxLines = 1,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Number,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
onValueChange = { newValue ->
|
||||
text = inputFilter(newValue)
|
||||
},
|
||||
|
||||
@@ -1,528 +0,0 @@
|
||||
package io.github.miuzarte.scrcpyforandroid.services
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import io.github.miuzarte.scrcpyforandroid.constants.AppDefaults
|
||||
import io.github.miuzarte.scrcpyforandroid.constants.AppPreferenceKeys
|
||||
|
||||
internal data class MainSettings(
|
||||
val audioEnabled: Boolean = AppDefaults.AUDIO_ENABLED,
|
||||
val audioCodec: String = AppDefaults.AUDIO_CODEC,
|
||||
val videoCodec: String = AppDefaults.VIDEO_CODEC,
|
||||
val themeBaseIndex: Int = AppDefaults.THEME_BASE_INDEX,
|
||||
val monetEnabled: Boolean = AppDefaults.MONET,
|
||||
val fullscreenDebugInfoEnabled: Boolean = AppDefaults.FULLSCREEN_DEBUG_INFO,
|
||||
val showFullscreenVirtualButtons: Boolean = AppDefaults.SHOW_FULLSCREEN_VIRTUAL_BUTTONS,
|
||||
val showPreviewVirtualButtonText: Boolean = AppDefaults.PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT,
|
||||
val keepScreenOnWhenStreamingEnabled: Boolean = AppDefaults.KEEP_SCREEN_ON_WHEN_STREAMING,
|
||||
val devicePreviewCardHeightDp: Int = AppDefaults.DEVICE_PREVIEW_CARD_HEIGHT_DP,
|
||||
val virtualButtonsLayout: String = AppDefaults.VIRTUAL_BUTTONS_LAYOUT,
|
||||
val customServerUri: String? = AppDefaults.CUSTOM_SERVER_URI,
|
||||
val serverRemotePath: String = AppDefaults.SERVER_REMOTE_PATH_INPUT,
|
||||
val adbKeyName: String = AppDefaults.ADB_KEY_NAME_INPUT,
|
||||
val adbPairingAutoDiscoverOnDialogOpen: Boolean =
|
||||
AppDefaults.ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN,
|
||||
val adbAutoReconnectPairedDevice: Boolean = AppDefaults.ADB_AUTO_RECONNECT_PAIRED_DEVICE,
|
||||
val adbMdnsLanDiscoveryEnabled: Boolean = AppDefaults.ADB_MDNS_LAN_DISCOVERY,
|
||||
)
|
||||
|
||||
internal data class DevicePageSettings(
|
||||
val quickConnectInput: String = AppDefaults.QUICK_CONNECT_INPUT,
|
||||
val pairHost: String = AppDefaults.PAIR_HOST,
|
||||
val pairPort: String = AppDefaults.PAIR_PORT,
|
||||
val pairCode: String = AppDefaults.PAIR_CODE,
|
||||
val audioBitRateKbps: Int = AppDefaults.AUDIO_BIT_RATE_KBPS,
|
||||
val audioBitRateInput: String = AppDefaults.AUDIO_BIT_RATE_INPUT,
|
||||
val videoBitRateMbps: Float = AppDefaults.VIDEO_BIT_RATE_MBPS,
|
||||
val videoBitRateInput: String = AppDefaults.VIDEO_BIT_RATE_INPUT,
|
||||
val turnScreenOff: Boolean = AppDefaults.TURN_SCREEN_OFF,
|
||||
val noControl: Boolean = AppDefaults.NO_CONTROL,
|
||||
val noVideo: Boolean = AppDefaults.NO_VIDEO,
|
||||
val videoSourcePreset: String = AppDefaults.VIDEO_SOURCE_PRESET,
|
||||
val displayIdInput: String = AppDefaults.DISPLAY_ID,
|
||||
val cameraIdInput: String = AppDefaults.CAMERA_ID,
|
||||
val cameraFacingPreset: String = AppDefaults.CAMERA_FACING_PRESET,
|
||||
val cameraSizePreset: String = AppDefaults.CAMERA_SIZE_PRESET,
|
||||
val cameraSizeCustom: String = AppDefaults.CAMERA_SIZE_CUSTOM,
|
||||
val cameraAr: String = AppDefaults.CAMERA_AR,
|
||||
val cameraFps: String = AppDefaults.CAMERA_FPS,
|
||||
val cameraHighSpeed: Boolean = AppDefaults.CAMERA_HIGH_SPEED,
|
||||
val audioSourcePreset: String = AppDefaults.AUDIO_SOURCE_PRESET,
|
||||
val audioSourceCustom: String = AppDefaults.AUDIO_SOURCE_CUSTOM,
|
||||
val audioDup: Boolean = AppDefaults.AUDIO_DUP,
|
||||
val noAudioPlayback: Boolean = AppDefaults.NO_AUDIO_PLAYBACK,
|
||||
val requireAudio: Boolean = AppDefaults.REQUIRE_AUDIO,
|
||||
val maxSizeInput: String = AppDefaults.MAX_SIZE_INPUT,
|
||||
val maxFpsInput: String = AppDefaults.MAX_FPS_INPUT,
|
||||
val videoEncoder: String = AppDefaults.VIDEO_ENCODER,
|
||||
val videoCodecOptions: String = AppDefaults.VIDEO_CODEC_OPTION,
|
||||
val audioEncoder: String = AppDefaults.AUDIO_ENCODER,
|
||||
val audioCodecOptions: String = AppDefaults.AUDIO_CODEC_OPTION,
|
||||
val newDisplayWidth: String = AppDefaults.NEW_DISPLAY_WIDTH,
|
||||
val newDisplayHeight: String = AppDefaults.NEW_DISPLAY_HEIGHT,
|
||||
val newDisplayDpi: String = AppDefaults.NEW_DISPLAY_DPI,
|
||||
val cropWidth: String = AppDefaults.CROP_WIDTH,
|
||||
val cropHeight: String = AppDefaults.CROP_HEIGHT,
|
||||
val cropX: String = AppDefaults.CROP_X,
|
||||
val cropY: String = AppDefaults.CROP_Y,
|
||||
)
|
||||
|
||||
internal fun loadMainSettings(context: Context): MainSettings {
|
||||
val prefs = context.getSharedPreferences(
|
||||
AppPreferenceKeys.PREFS_NAME,
|
||||
Context.MODE_PRIVATE,
|
||||
)
|
||||
return MainSettings(
|
||||
audioEnabled = prefs.getBoolean(
|
||||
AppPreferenceKeys.AUDIO_ENABLED,
|
||||
AppDefaults.AUDIO_ENABLED,
|
||||
),
|
||||
audioCodec = prefs.getString(
|
||||
AppPreferenceKeys.AUDIO_CODEC,
|
||||
AppDefaults.AUDIO_CODEC,
|
||||
).orEmpty().ifBlank { AppDefaults.AUDIO_CODEC },
|
||||
videoCodec = prefs.getString(
|
||||
AppPreferenceKeys.VIDEO_CODEC,
|
||||
AppDefaults.VIDEO_CODEC,
|
||||
).orEmpty().ifBlank { AppDefaults.VIDEO_CODEC },
|
||||
themeBaseIndex = prefs.getInt(
|
||||
AppPreferenceKeys.THEME_BASE_INDEX,
|
||||
AppDefaults.THEME_BASE_INDEX,
|
||||
),
|
||||
monetEnabled = prefs.getBoolean(
|
||||
AppPreferenceKeys.MONET,
|
||||
AppDefaults.MONET,
|
||||
),
|
||||
fullscreenDebugInfoEnabled = prefs.getBoolean(
|
||||
AppPreferenceKeys.FULLSCREEN_DEBUG_INFO,
|
||||
AppDefaults.FULLSCREEN_DEBUG_INFO,
|
||||
),
|
||||
showFullscreenVirtualButtons = prefs.getBoolean(
|
||||
AppPreferenceKeys.SHOW_FULLSCREEN_VIRTUAL_BUTTONS,
|
||||
AppDefaults.SHOW_FULLSCREEN_VIRTUAL_BUTTONS,
|
||||
),
|
||||
showPreviewVirtualButtonText = prefs.getBoolean(
|
||||
AppPreferenceKeys.PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT,
|
||||
AppDefaults.PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT,
|
||||
),
|
||||
keepScreenOnWhenStreamingEnabled = prefs.getBoolean(
|
||||
AppPreferenceKeys.KEEP_SCREEN_ON_WHEN_STREAMING,
|
||||
AppDefaults.KEEP_SCREEN_ON_WHEN_STREAMING,
|
||||
),
|
||||
devicePreviewCardHeightDp = prefs.getInt(
|
||||
AppPreferenceKeys.DEVICE_PREVIEW_CARD_HEIGHT_DP,
|
||||
AppDefaults.DEVICE_PREVIEW_CARD_HEIGHT_DP,
|
||||
).coerceAtLeast(120),
|
||||
virtualButtonsLayout = prefs.getString(
|
||||
AppPreferenceKeys.VIRTUAL_BUTTONS_LAYOUT,
|
||||
AppDefaults.VIRTUAL_BUTTONS_LAYOUT,
|
||||
).orEmpty().ifBlank { AppDefaults.VIRTUAL_BUTTONS_LAYOUT },
|
||||
customServerUri = prefs.getString(
|
||||
AppPreferenceKeys.CUSTOM_SERVER_URI,
|
||||
AppDefaults.CUSTOM_SERVER_URI
|
||||
).orEmpty().ifBlank { null },
|
||||
serverRemotePath = prefs.getString(
|
||||
AppPreferenceKeys.SERVER_REMOTE_PATH,
|
||||
AppDefaults.SERVER_REMOTE_PATH_INPUT,
|
||||
).orEmpty(),
|
||||
adbKeyName = prefs.getString(
|
||||
AppPreferenceKeys.ADB_KEY_NAME,
|
||||
AppDefaults.ADB_KEY_NAME_INPUT,
|
||||
).orEmpty(),
|
||||
adbPairingAutoDiscoverOnDialogOpen = prefs.getBoolean(
|
||||
AppPreferenceKeys.ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN,
|
||||
AppDefaults.ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN,
|
||||
),
|
||||
adbAutoReconnectPairedDevice = prefs.getBoolean(
|
||||
AppPreferenceKeys.ADB_AUTO_RECONNECT_PAIRED_DEVICE,
|
||||
AppDefaults.ADB_AUTO_RECONNECT_PAIRED_DEVICE,
|
||||
),
|
||||
adbMdnsLanDiscoveryEnabled = prefs.getBoolean(
|
||||
AppPreferenceKeys.ADB_MDNS_LAN_DISCOVERY,
|
||||
AppDefaults.ADB_MDNS_LAN_DISCOVERY,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
internal fun saveMainSettings(context: Context, settings: MainSettings) {
|
||||
context.getSharedPreferences(
|
||||
AppPreferenceKeys.PREFS_NAME,
|
||||
Context.MODE_PRIVATE,
|
||||
).edit {
|
||||
putBoolean(
|
||||
AppPreferenceKeys.AUDIO_ENABLED,
|
||||
settings.audioEnabled,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.AUDIO_CODEC,
|
||||
settings.audioCodec,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.VIDEO_CODEC,
|
||||
settings.videoCodec,
|
||||
)
|
||||
.putInt(
|
||||
AppPreferenceKeys.THEME_BASE_INDEX,
|
||||
settings.themeBaseIndex,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.MONET,
|
||||
settings.monetEnabled,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.FULLSCREEN_DEBUG_INFO,
|
||||
settings.fullscreenDebugInfoEnabled,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.SHOW_FULLSCREEN_VIRTUAL_BUTTONS,
|
||||
settings.showFullscreenVirtualButtons,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT,
|
||||
settings.showPreviewVirtualButtonText,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.KEEP_SCREEN_ON_WHEN_STREAMING,
|
||||
settings.keepScreenOnWhenStreamingEnabled,
|
||||
)
|
||||
.putInt(
|
||||
AppPreferenceKeys.DEVICE_PREVIEW_CARD_HEIGHT_DP,
|
||||
settings.devicePreviewCardHeightDp.coerceAtLeast(120),
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.VIRTUAL_BUTTONS_LAYOUT,
|
||||
settings.virtualButtonsLayout,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CUSTOM_SERVER_URI,
|
||||
settings.customServerUri,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.SERVER_REMOTE_PATH,
|
||||
settings.serverRemotePath,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.ADB_KEY_NAME,
|
||||
settings.adbKeyName,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN,
|
||||
settings.adbPairingAutoDiscoverOnDialogOpen,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.ADB_AUTO_RECONNECT_PAIRED_DEVICE,
|
||||
settings.adbAutoReconnectPairedDevice,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.ADB_MDNS_LAN_DISCOVERY,
|
||||
settings.adbMdnsLanDiscoveryEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun loadDevicePageSettings(context: Context): DevicePageSettings {
|
||||
val prefs = context.getSharedPreferences(
|
||||
AppPreferenceKeys.PREFS_NAME,
|
||||
Context.MODE_PRIVATE,
|
||||
)
|
||||
val audioBitRateKbps = prefs.getInt(
|
||||
AppPreferenceKeys.AUDIO_BIT_RATE_KBPS,
|
||||
AppDefaults.AUDIO_BIT_RATE_KBPS,
|
||||
)
|
||||
return DevicePageSettings(
|
||||
quickConnectInput = prefs.getString(
|
||||
AppPreferenceKeys.QUICK_CONNECT_INPUT,
|
||||
AppDefaults.QUICK_CONNECT_INPUT,
|
||||
).orEmpty(),
|
||||
pairHost = AppDefaults.PAIR_HOST,
|
||||
pairPort = AppDefaults.PAIR_PORT,
|
||||
pairCode = AppDefaults.PAIR_CODE,
|
||||
audioBitRateKbps = audioBitRateKbps,
|
||||
audioBitRateInput = prefs.getString(
|
||||
AppPreferenceKeys.AUDIO_BIT_RATE_INPUT,
|
||||
AppDefaults.AUDIO_BIT_RATE_INPUT,
|
||||
).orEmpty().ifBlank { audioBitRateKbps.toString() },
|
||||
videoBitRateMbps = prefs.getFloat(
|
||||
AppPreferenceKeys.VIDEO_BIT_RATE_MBPS,
|
||||
AppDefaults.VIDEO_BIT_RATE_MBPS,
|
||||
),
|
||||
videoBitRateInput = prefs.getString(
|
||||
AppPreferenceKeys.VIDEO_BIT_RATE_INPUT,
|
||||
AppDefaults.VIDEO_BIT_RATE_INPUT
|
||||
).orEmpty().ifBlank { AppDefaults.VIDEO_BIT_RATE_INPUT },
|
||||
turnScreenOff = prefs.getBoolean(
|
||||
AppPreferenceKeys.TURN_SCREEN_OFF,
|
||||
AppDefaults.TURN_SCREEN_OFF,
|
||||
),
|
||||
noControl = prefs.getBoolean(
|
||||
AppPreferenceKeys.NO_CONTROL,
|
||||
AppDefaults.NO_CONTROL,
|
||||
),
|
||||
noVideo = prefs.getBoolean(
|
||||
AppPreferenceKeys.NO_VIDEO,
|
||||
AppDefaults.NO_VIDEO,
|
||||
),
|
||||
videoSourcePreset = prefs.getString(
|
||||
AppPreferenceKeys.VIDEO_SOURCE_PRESET,
|
||||
AppDefaults.VIDEO_SOURCE_PRESET,
|
||||
).orEmpty().ifBlank { AppDefaults.VIDEO_SOURCE_PRESET },
|
||||
displayIdInput = prefs.getString(
|
||||
AppPreferenceKeys.DISPLAY_ID,
|
||||
AppDefaults.DISPLAY_ID,
|
||||
)
|
||||
.orEmpty(),
|
||||
cameraIdInput = prefs.getString(
|
||||
AppPreferenceKeys.CAMERA_ID,
|
||||
AppDefaults.CAMERA_ID,
|
||||
)
|
||||
.orEmpty(),
|
||||
cameraFacingPreset = prefs.getString(
|
||||
AppPreferenceKeys.CAMERA_FACING_PRESET,
|
||||
AppDefaults.CAMERA_FACING_PRESET,
|
||||
).orEmpty(),
|
||||
cameraSizePreset = prefs.getString(
|
||||
AppPreferenceKeys.CAMERA_SIZE_PRESET,
|
||||
AppDefaults.CAMERA_SIZE_PRESET,
|
||||
).orEmpty(),
|
||||
cameraSizeCustom = prefs.getString(
|
||||
AppPreferenceKeys.CAMERA_SIZE_CUSTOM,
|
||||
AppDefaults.CAMERA_SIZE_CUSTOM,
|
||||
).orEmpty(),
|
||||
cameraAr = prefs.getString(
|
||||
AppPreferenceKeys.CAMERA_AR,
|
||||
AppDefaults.CAMERA_AR,
|
||||
).orEmpty(),
|
||||
cameraFps = prefs.getString(
|
||||
AppPreferenceKeys.CAMERA_FPS,
|
||||
AppDefaults.CAMERA_FPS,
|
||||
).orEmpty(),
|
||||
cameraHighSpeed = prefs.getBoolean(
|
||||
AppPreferenceKeys.CAMERA_HIGH_SPEED,
|
||||
AppDefaults.CAMERA_HIGH_SPEED,
|
||||
),
|
||||
audioSourcePreset = prefs.getString(
|
||||
AppPreferenceKeys.AUDIO_SOURCE_PRESET,
|
||||
AppDefaults.AUDIO_SOURCE_PRESET,
|
||||
).orEmpty().ifBlank { AppDefaults.AUDIO_SOURCE_PRESET },
|
||||
audioSourceCustom = prefs.getString(
|
||||
AppPreferenceKeys.AUDIO_SOURCE_CUSTOM,
|
||||
AppDefaults.AUDIO_SOURCE_CUSTOM,
|
||||
).orEmpty(),
|
||||
audioDup = prefs.getBoolean(
|
||||
AppPreferenceKeys.AUDIO_DUP,
|
||||
AppDefaults.AUDIO_DUP,
|
||||
),
|
||||
noAudioPlayback = prefs.getBoolean(
|
||||
AppPreferenceKeys.NO_AUDIO_PLAYBACK,
|
||||
AppDefaults.NO_AUDIO_PLAYBACK,
|
||||
),
|
||||
requireAudio = prefs.getBoolean(
|
||||
AppPreferenceKeys.REQUIRE_AUDIO,
|
||||
AppDefaults.REQUIRE_AUDIO,
|
||||
),
|
||||
maxSizeInput = prefs.getString(
|
||||
AppPreferenceKeys.MAX_SIZE_INPUT,
|
||||
AppDefaults.MAX_SIZE_INPUT,
|
||||
)
|
||||
.orEmpty(),
|
||||
maxFpsInput = prefs.getString(
|
||||
AppPreferenceKeys.MAX_FPS_INPUT,
|
||||
AppDefaults.MAX_FPS_INPUT,
|
||||
)
|
||||
.orEmpty(),
|
||||
videoEncoder = prefs.getString(
|
||||
AppPreferenceKeys.VIDEO_ENCODER,
|
||||
AppDefaults.VIDEO_ENCODER,
|
||||
)
|
||||
.orEmpty(),
|
||||
videoCodecOptions = prefs.getString(
|
||||
AppPreferenceKeys.VIDEO_CODEC_OPTION,
|
||||
AppDefaults.VIDEO_CODEC_OPTION,
|
||||
).orEmpty(),
|
||||
audioEncoder = prefs.getString(
|
||||
AppPreferenceKeys.AUDIO_ENCODER,
|
||||
AppDefaults.AUDIO_ENCODER,
|
||||
).orEmpty(),
|
||||
audioCodecOptions = prefs.getString(
|
||||
AppPreferenceKeys.AUDIO_CODEC_OPTION,
|
||||
AppDefaults.AUDIO_CODEC_OPTION,
|
||||
).orEmpty(),
|
||||
newDisplayWidth = prefs.getString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_WIDTH,
|
||||
AppDefaults.NEW_DISPLAY_WIDTH,
|
||||
).orEmpty(),
|
||||
newDisplayHeight = prefs.getString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_HEIGHT,
|
||||
AppDefaults.NEW_DISPLAY_HEIGHT,
|
||||
).orEmpty(),
|
||||
newDisplayDpi = prefs.getString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_DPI,
|
||||
AppDefaults.NEW_DISPLAY_DPI,
|
||||
).orEmpty(),
|
||||
cropWidth = prefs.getString(
|
||||
AppPreferenceKeys.CROP_WIDTH,
|
||||
AppDefaults.CROP_WIDTH,
|
||||
).orEmpty(),
|
||||
cropHeight = prefs.getString(
|
||||
AppPreferenceKeys.CROP_HEIGHT,
|
||||
AppDefaults.CROP_HEIGHT,
|
||||
).orEmpty(),
|
||||
cropX = prefs.getString(
|
||||
AppPreferenceKeys.CROP_X,
|
||||
AppDefaults.CROP_X,
|
||||
).orEmpty(),
|
||||
cropY = prefs.getString(
|
||||
AppPreferenceKeys.CROP_Y,
|
||||
AppDefaults.CROP_Y,
|
||||
).orEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
internal fun saveDevicePageSettings(context: Context, settings: DevicePageSettings) {
|
||||
context.getSharedPreferences(AppPreferenceKeys.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
.edit {
|
||||
remove(AppPreferenceKeys.PAIR_HOST)
|
||||
.remove(AppPreferenceKeys.PAIR_PORT)
|
||||
.remove(AppPreferenceKeys.PAIR_CODE)
|
||||
.putString(
|
||||
AppPreferenceKeys.QUICK_CONNECT_INPUT,
|
||||
settings.quickConnectInput,
|
||||
)
|
||||
.putInt(
|
||||
AppPreferenceKeys.AUDIO_BIT_RATE_KBPS,
|
||||
settings.audioBitRateKbps,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.AUDIO_BIT_RATE_INPUT,
|
||||
settings.audioBitRateInput,
|
||||
)
|
||||
.putFloat(
|
||||
AppPreferenceKeys.VIDEO_BIT_RATE_MBPS,
|
||||
settings.videoBitRateMbps,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.VIDEO_BIT_RATE_INPUT,
|
||||
settings.videoBitRateInput,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.TURN_SCREEN_OFF,
|
||||
settings.turnScreenOff,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.NO_CONTROL,
|
||||
settings.noControl,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.NO_VIDEO,
|
||||
settings.noVideo,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.VIDEO_SOURCE_PRESET,
|
||||
settings.videoSourcePreset,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.DISPLAY_ID,
|
||||
settings.displayIdInput,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CAMERA_ID,
|
||||
settings.cameraIdInput,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CAMERA_FACING_PRESET,
|
||||
settings.cameraFacingPreset,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CAMERA_SIZE_PRESET,
|
||||
settings.cameraSizePreset,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CAMERA_SIZE_CUSTOM,
|
||||
settings.cameraSizeCustom,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CAMERA_AR,
|
||||
settings.cameraAr,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CAMERA_FPS,
|
||||
settings.cameraFps,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.CAMERA_HIGH_SPEED,
|
||||
settings.cameraHighSpeed,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.AUDIO_SOURCE_PRESET,
|
||||
settings.audioSourcePreset,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.AUDIO_SOURCE_CUSTOM,
|
||||
settings.audioSourceCustom,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.AUDIO_DUP,
|
||||
settings.audioDup,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.NO_AUDIO_PLAYBACK,
|
||||
settings.noAudioPlayback,
|
||||
)
|
||||
.putBoolean(
|
||||
AppPreferenceKeys.REQUIRE_AUDIO,
|
||||
settings.requireAudio,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.MAX_SIZE_INPUT,
|
||||
settings.maxSizeInput,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.MAX_FPS_INPUT,
|
||||
settings.maxFpsInput,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.VIDEO_ENCODER,
|
||||
settings.videoEncoder,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.VIDEO_CODEC_OPTION,
|
||||
settings.videoCodecOptions,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.AUDIO_ENCODER,
|
||||
settings.audioEncoder,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.AUDIO_CODEC_OPTION,
|
||||
settings.audioCodecOptions,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_WIDTH,
|
||||
settings.newDisplayWidth,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_HEIGHT,
|
||||
settings.newDisplayHeight,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_DPI,
|
||||
settings.newDisplayDpi,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CROP_WIDTH,
|
||||
settings.cropWidth,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CROP_HEIGHT,
|
||||
settings.cropHeight,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CROP_X,
|
||||
settings.cropX,
|
||||
)
|
||||
.putString(
|
||||
AppPreferenceKeys.CROP_Y,
|
||||
settings.cropY,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import java.util.Locale
|
||||
object EventLogger {
|
||||
private const val LOG_TAG = "EventLogger"
|
||||
|
||||
const val MAX_LINES = 512
|
||||
|
||||
private val _eventLog: SnapshotStateList<String> = mutableStateListOf()
|
||||
|
||||
/**
|
||||
@@ -36,8 +38,8 @@ object EventLogger {
|
||||
_eventLog.add(0, "[$timestamp] $message")
|
||||
|
||||
// Rotate logs if exceeds max size
|
||||
if (_eventLog.size > Defaults.EVENT_LOG_LINES) {
|
||||
_eventLog.removeRange(Defaults.EVENT_LOG_LINES, _eventLog.size)
|
||||
if (_eventLog.size > MAX_LINES) {
|
||||
_eventLog.removeRange(MAX_LINES, _eventLog.size)
|
||||
}
|
||||
|
||||
// Log to Android logcat
|
||||
|
||||
@@ -28,10 +28,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
||||
booleanPreferencesKey("show_fullscreen_virtual_buttons"),
|
||||
true
|
||||
)
|
||||
val KEEP_SCREEN_ON_WHEN_STREAMING = Pair(
|
||||
booleanPreferencesKey("keep_screen_on_when_streaming"),
|
||||
false
|
||||
)
|
||||
val DEVICE_PREVIEW_CARD_HEIGHT_DP = Pair(
|
||||
intPreferencesKey("device_preview_card_height_dp"),
|
||||
320
|
||||
@@ -81,7 +77,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
||||
// Scrcpy Settings
|
||||
val fullscreenDebugInfo by setting(FULLSCREEN_DEBUG_INFO)
|
||||
val showFullscreenVirtualButtons by setting(SHOW_FULLSCREEN_VIRTUAL_BUTTONS)
|
||||
val keepScreenOnWhenStreaming by setting(KEEP_SCREEN_ON_WHEN_STREAMING)
|
||||
val devicePreviewCardHeightDp by setting(DEVICE_PREVIEW_CARD_HEIGHT_DP)
|
||||
val previewVirtualButtonShowText by setting(PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT)
|
||||
val virtualButtonsLayout by setting(VIRTUAL_BUTTONS_LAYOUT)
|
||||
@@ -103,7 +98,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
||||
val monet: Boolean,
|
||||
val fullscreenDebugInfo: Boolean,
|
||||
val showFullscreenVirtualButtons: Boolean,
|
||||
val keepScreenOnWhenStreaming: Boolean,
|
||||
val devicePreviewCardHeightDp: Int,
|
||||
val previewVirtualButtonShowText: Boolean,
|
||||
val virtualButtonsLayout: String,
|
||||
@@ -122,7 +116,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
||||
bundleField(MONET) { bundle: Bundle -> bundle.monet },
|
||||
bundleField(FULLSCREEN_DEBUG_INFO) { bundle: Bundle -> bundle.fullscreenDebugInfo },
|
||||
bundleField(SHOW_FULLSCREEN_VIRTUAL_BUTTONS) { bundle: Bundle -> bundle.showFullscreenVirtualButtons },
|
||||
bundleField(KEEP_SCREEN_ON_WHEN_STREAMING) { bundle: Bundle -> bundle.keepScreenOnWhenStreaming },
|
||||
bundleField(DEVICE_PREVIEW_CARD_HEIGHT_DP) { bundle: Bundle -> bundle.devicePreviewCardHeightDp },
|
||||
bundleField(PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT) { bundle: Bundle -> bundle.previewVirtualButtonShowText },
|
||||
bundleField(VIRTUAL_BUTTONS_LAYOUT) { bundle: Bundle -> bundle.virtualButtonsLayout },
|
||||
@@ -142,7 +135,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
||||
monet = preferences.read(MONET),
|
||||
fullscreenDebugInfo = preferences.read(FULLSCREEN_DEBUG_INFO),
|
||||
showFullscreenVirtualButtons = preferences.read(SHOW_FULLSCREEN_VIRTUAL_BUTTONS),
|
||||
keepScreenOnWhenStreaming = preferences.read(KEEP_SCREEN_ON_WHEN_STREAMING),
|
||||
devicePreviewCardHeightDp = preferences.read(DEVICE_PREVIEW_CARD_HEIGHT_DP),
|
||||
previewVirtualButtonShowText = preferences.read(PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT),
|
||||
virtualButtonsLayout = preferences.read(VIRTUAL_BUTTONS_LAYOUT),
|
||||
|
||||
@@ -4,8 +4,6 @@ import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import androidx.core.content.edit
|
||||
import io.github.miuzarte.scrcpyforandroid.constants.AppDefaults
|
||||
import io.github.miuzarte.scrcpyforandroid.constants.AppPreferenceKeys
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@@ -16,7 +14,7 @@ private const val TAG = "PreferenceMigration"
|
||||
*/
|
||||
class PreferenceMigration(private val appContext: Context) {
|
||||
private val appSharedPrefs: SharedPreferences by lazy {
|
||||
appContext.getSharedPreferences(AppPreferenceKeys.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
appContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
private val sharedPrefs: SharedPreferences by lazy {
|
||||
@@ -80,80 +78,75 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
|
||||
// Theme Settings
|
||||
migrateInt(
|
||||
AppPreferenceKeys.THEME_BASE_INDEX,
|
||||
AppDefaults.THEME_BASE_INDEX,
|
||||
appSettings.themeBaseIndex
|
||||
THEME_BASE_INDEX,
|
||||
AppSettings.THEME_BASE_INDEX.defaultValue,
|
||||
appSettings.themeBaseIndex,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.MONET,
|
||||
AppDefaults.MONET,
|
||||
appSettings.monet
|
||||
MONET,
|
||||
AppSettings.MONET.defaultValue,
|
||||
appSettings.monet,
|
||||
)
|
||||
|
||||
// Scrcpy Settings
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.FULLSCREEN_DEBUG_INFO,
|
||||
AppDefaults.FULLSCREEN_DEBUG_INFO,
|
||||
appSettings.fullscreenDebugInfo
|
||||
FULLSCREEN_DEBUG_INFO,
|
||||
AppSettings.FULLSCREEN_DEBUG_INFO.defaultValue,
|
||||
appSettings.fullscreenDebugInfo,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.SHOW_FULLSCREEN_VIRTUAL_BUTTONS,
|
||||
AppDefaults.SHOW_FULLSCREEN_VIRTUAL_BUTTONS,
|
||||
appSettings.showFullscreenVirtualButtons
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.KEEP_SCREEN_ON_WHEN_STREAMING,
|
||||
AppDefaults.KEEP_SCREEN_ON_WHEN_STREAMING,
|
||||
appSettings.keepScreenOnWhenStreaming
|
||||
SHOW_FULLSCREEN_VIRTUAL_BUTTONS,
|
||||
AppSettings.SHOW_FULLSCREEN_VIRTUAL_BUTTONS.defaultValue,
|
||||
appSettings.showFullscreenVirtualButtons,
|
||||
)
|
||||
migrateInt(
|
||||
AppPreferenceKeys.DEVICE_PREVIEW_CARD_HEIGHT_DP,
|
||||
AppDefaults.DEVICE_PREVIEW_CARD_HEIGHT_DP,
|
||||
appSettings.devicePreviewCardHeightDp
|
||||
DEVICE_PREVIEW_CARD_HEIGHT_DP,
|
||||
AppSettings.DEVICE_PREVIEW_CARD_HEIGHT_DP.defaultValue,
|
||||
appSettings.devicePreviewCardHeightDp,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT,
|
||||
AppDefaults.PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT,
|
||||
appSettings.previewVirtualButtonShowText
|
||||
PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT,
|
||||
AppSettings.PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT.defaultValue,
|
||||
appSettings.previewVirtualButtonShowText,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.VIRTUAL_BUTTONS_LAYOUT,
|
||||
AppDefaults.VIRTUAL_BUTTONS_LAYOUT,
|
||||
appSettings.virtualButtonsLayout
|
||||
VIRTUAL_BUTTONS_LAYOUT,
|
||||
AppSettings.VIRTUAL_BUTTONS_LAYOUT.defaultValue,
|
||||
appSettings.virtualButtonsLayout,
|
||||
)
|
||||
|
||||
// Scrcpy Server Settings
|
||||
migrateString(
|
||||
AppPreferenceKeys.CUSTOM_SERVER_URI,
|
||||
AppDefaults.CUSTOM_SERVER_URI ?: "",
|
||||
appSettings.customServerUri
|
||||
CUSTOM_SERVER_URI,
|
||||
AppSettings.CUSTOM_SERVER_URI.defaultValue,
|
||||
appSettings.customServerUri,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.SERVER_REMOTE_PATH,
|
||||
AppDefaults.SERVER_REMOTE_PATH_INPUT,
|
||||
appSettings.serverRemotePath
|
||||
SERVER_REMOTE_PATH,
|
||||
AppSettings.SERVER_REMOTE_PATH.defaultValue,
|
||||
appSettings.serverRemotePath,
|
||||
)
|
||||
|
||||
// ADB Settings
|
||||
migrateString(
|
||||
AppPreferenceKeys.ADB_KEY_NAME,
|
||||
AppDefaults.ADB_KEY_NAME_INPUT,
|
||||
appSettings.adbKeyName
|
||||
ADB_KEY_NAME,
|
||||
AppSettings.ADB_KEY_NAME.defaultValue,
|
||||
appSettings.adbKeyName,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN,
|
||||
AppDefaults.ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN,
|
||||
appSettings.adbPairingAutoDiscoverOnDialogOpen
|
||||
ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN,
|
||||
AppSettings.ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN.defaultValue,
|
||||
appSettings.adbPairingAutoDiscoverOnDialogOpen,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.ADB_AUTO_RECONNECT_PAIRED_DEVICE,
|
||||
AppDefaults.ADB_AUTO_RECONNECT_PAIRED_DEVICE,
|
||||
appSettings.adbAutoReconnectPairedDevice
|
||||
ADB_AUTO_RECONNECT_PAIRED_DEVICE,
|
||||
AppSettings.ADB_AUTO_RECONNECT_PAIRED_DEVICE.defaultValue,
|
||||
appSettings.adbAutoReconnectPairedDevice,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.ADB_MDNS_LAN_DISCOVERY,
|
||||
AppDefaults.ADB_MDNS_LAN_DISCOVERY,
|
||||
appSettings.adbMdnsLanDiscovery
|
||||
ADB_MDNS_LAN_DISCOVERY,
|
||||
AppSettings.ADB_MDNS_LAN_DISCOVERY.defaultValue,
|
||||
appSettings.adbMdnsLanDiscovery,
|
||||
)
|
||||
|
||||
Log.d(TAG, "AppSettings migration completed")
|
||||
@@ -167,114 +160,115 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
|
||||
// Audio & Video Codecs
|
||||
migrateString(
|
||||
AppPreferenceKeys.AUDIO_CODEC,
|
||||
AppDefaults.AUDIO_CODEC,
|
||||
scrcpyOptions.audioCodec
|
||||
AUDIO_CODEC,
|
||||
ScrcpyOptions.AUDIO_CODEC.defaultValue,
|
||||
scrcpyOptions.audioCodec,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.VIDEO_CODEC,
|
||||
AppDefaults.VIDEO_CODEC,
|
||||
scrcpyOptions.videoCodec
|
||||
VIDEO_CODEC,
|
||||
ScrcpyOptions.VIDEO_CODEC.defaultValue,
|
||||
scrcpyOptions.videoCodec,
|
||||
)
|
||||
|
||||
// Bit Rates
|
||||
val audioBitRateKbps = sharedPrefs.getInt(
|
||||
AppPreferenceKeys.AUDIO_BIT_RATE_KBPS,
|
||||
AppDefaults.AUDIO_BIT_RATE_KBPS
|
||||
AUDIO_BIT_RATE_KBPS,
|
||||
ScrcpyOptions.AUDIO_BIT_RATE.defaultValue / 1_000,
|
||||
)
|
||||
scrcpyOptions.audioBitRate.set(audioBitRateKbps * 1000) // Convert to bps
|
||||
scrcpyOptions.audioBitRate.set(audioBitRateKbps * 1_000) // Convert to bps
|
||||
|
||||
val videoBitRateMbps = sharedPrefs.getFloat(
|
||||
AppPreferenceKeys.VIDEO_BIT_RATE_MBPS,
|
||||
AppDefaults.VIDEO_BIT_RATE_MBPS
|
||||
VIDEO_BIT_RATE_MBPS,
|
||||
(ScrcpyOptions.VIDEO_BIT_RATE.defaultValue / 1_000_000).toFloat(),
|
||||
)
|
||||
scrcpyOptions.videoBitRate.set((videoBitRateMbps * 1_000_000).toInt())
|
||||
|
||||
// Control Options
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.TURN_SCREEN_OFF,
|
||||
AppDefaults.TURN_SCREEN_OFF,
|
||||
scrcpyOptions.turnScreenOff
|
||||
TURN_SCREEN_OFF,
|
||||
ScrcpyOptions.TURN_SCREEN_OFF.defaultValue,
|
||||
scrcpyOptions.turnScreenOff,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.NO_CONTROL,
|
||||
AppDefaults.NO_CONTROL
|
||||
NO_CONTROL,
|
||||
!ScrcpyOptions.CONTROL.defaultValue,
|
||||
) { value ->
|
||||
scrcpyOptions.control.set(!value) // Invert logic
|
||||
}
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.NO_VIDEO,
|
||||
AppDefaults.NO_VIDEO
|
||||
NO_VIDEO,
|
||||
!ScrcpyOptions.VIDEO.defaultValue,
|
||||
) { value ->
|
||||
scrcpyOptions.video.set(!value) // Invert logic
|
||||
}
|
||||
|
||||
// Video Source
|
||||
val videoSourcePreset = sharedPrefs.getString(
|
||||
AppPreferenceKeys.VIDEO_SOURCE_PRESET,
|
||||
AppDefaults.VIDEO_SOURCE_PRESET
|
||||
).orEmpty().ifBlank { AppDefaults.VIDEO_SOURCE_PRESET }
|
||||
VIDEO_SOURCE_PRESET,
|
||||
ScrcpyOptions.VIDEO_SOURCE.defaultValue,
|
||||
).orEmpty().ifBlank { ScrcpyOptions.VIDEO_SOURCE.defaultValue }
|
||||
scrcpyOptions.videoSource.set(videoSourcePreset)
|
||||
|
||||
migrateString(
|
||||
AppPreferenceKeys.DISPLAY_ID,
|
||||
AppDefaults.DISPLAY_ID
|
||||
DISPLAY_ID,
|
||||
ScrcpyOptions.DISPLAY_ID.defaultValue.toString(),
|
||||
) { value ->
|
||||
value.toIntOrNull()?.let { scrcpyOptions.displayId.set(it) }
|
||||
}
|
||||
|
||||
// Camera Settings
|
||||
migrateString(
|
||||
AppPreferenceKeys.CAMERA_ID,
|
||||
AppDefaults.CAMERA_ID,
|
||||
scrcpyOptions.cameraId
|
||||
CAMERA_ID,
|
||||
ScrcpyOptions.CAMERA_ID.defaultValue,
|
||||
scrcpyOptions.cameraId,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.CAMERA_FACING_PRESET,
|
||||
AppDefaults.CAMERA_FACING_PRESET,
|
||||
scrcpyOptions.cameraFacing
|
||||
CAMERA_FACING_PRESET,
|
||||
ScrcpyOptions.CAMERA_FACING.defaultValue,
|
||||
scrcpyOptions.cameraFacing,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.CAMERA_SIZE_PRESET,
|
||||
AppDefaults.CAMERA_SIZE_PRESET
|
||||
CAMERA_SIZE_PRESET,
|
||||
ScrcpyOptions.CAMERA_SIZE.defaultValue,
|
||||
) { value ->
|
||||
if (value == "custom") {
|
||||
val customSize = sharedPrefs.getString(
|
||||
AppPreferenceKeys.CAMERA_SIZE_CUSTOM,
|
||||
AppDefaults.CAMERA_SIZE_CUSTOM
|
||||
CAMERA_SIZE_CUSTOM,
|
||||
ScrcpyOptions.CAMERA_SIZE_CUSTOM.defaultValue,
|
||||
).orEmpty()
|
||||
scrcpyOptions.cameraSize.set(customSize)
|
||||
scrcpyOptions.cameraSizeCustom.set(customSize)
|
||||
scrcpyOptions.cameraSizeUseCustom.set(true)
|
||||
} else {
|
||||
scrcpyOptions.cameraSize.set(value)
|
||||
}
|
||||
}
|
||||
migrateString(
|
||||
AppPreferenceKeys.CAMERA_AR,
|
||||
AppDefaults.CAMERA_AR,
|
||||
scrcpyOptions.cameraAr
|
||||
CAMERA_AR,
|
||||
ScrcpyOptions.CAMERA_AR.defaultValue,
|
||||
scrcpyOptions.cameraAr,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.CAMERA_FPS,
|
||||
AppDefaults.CAMERA_FPS
|
||||
CAMERA_FPS,
|
||||
ScrcpyOptions.CAMERA_FPS.defaultValue.toString(),
|
||||
) { value ->
|
||||
value.toIntOrNull()?.let { scrcpyOptions.cameraFps.set(it) }
|
||||
}
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.CAMERA_HIGH_SPEED,
|
||||
AppDefaults.CAMERA_HIGH_SPEED,
|
||||
scrcpyOptions.cameraHighSpeed
|
||||
CAMERA_HIGH_SPEED,
|
||||
ScrcpyOptions.CAMERA_HIGH_SPEED.defaultValue,
|
||||
scrcpyOptions.cameraHighSpeed,
|
||||
)
|
||||
|
||||
// Audio Source
|
||||
val audioSourcePreset = sharedPrefs.getString(
|
||||
AppPreferenceKeys.AUDIO_SOURCE_PRESET,
|
||||
AppDefaults.AUDIO_SOURCE_PRESET
|
||||
).orEmpty().ifBlank { AppDefaults.AUDIO_SOURCE_PRESET }
|
||||
AUDIO_SOURCE_PRESET,
|
||||
"auto",
|
||||
).orEmpty().ifBlank { "auto" }
|
||||
|
||||
if (audioSourcePreset == "custom") {
|
||||
val customSource = sharedPrefs.getString(
|
||||
AppPreferenceKeys.AUDIO_SOURCE_CUSTOM,
|
||||
AppDefaults.AUDIO_SOURCE_CUSTOM
|
||||
AUDIO_SOURCE_CUSTOM,
|
||||
ScrcpyOptions.AUDIO_SOURCE.defaultValue,
|
||||
).orEmpty()
|
||||
scrcpyOptions.audioSource.set(customSource)
|
||||
} else {
|
||||
@@ -282,69 +276,69 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
}
|
||||
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.AUDIO_DUP,
|
||||
AppDefaults.AUDIO_DUP,
|
||||
scrcpyOptions.audioDup
|
||||
AUDIO_DUP,
|
||||
ScrcpyOptions.AUDIO_DUP.defaultValue,
|
||||
scrcpyOptions.audioDup,
|
||||
)
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.NO_AUDIO_PLAYBACK,
|
||||
AppDefaults.NO_AUDIO_PLAYBACK
|
||||
NO_AUDIO_PLAYBACK,
|
||||
!ScrcpyOptions.AUDIO_PLAYBACK.defaultValue,
|
||||
) { value ->
|
||||
scrcpyOptions.audioPlayback.set(!value) // Invert logic
|
||||
}
|
||||
migrateBoolean(
|
||||
AppPreferenceKeys.REQUIRE_AUDIO,
|
||||
AppDefaults.REQUIRE_AUDIO,
|
||||
scrcpyOptions.requireAudio
|
||||
REQUIRE_AUDIO,
|
||||
ScrcpyOptions.REQUIRE_AUDIO.defaultValue,
|
||||
scrcpyOptions.requireAudio,
|
||||
)
|
||||
|
||||
// Max Size & FPS
|
||||
migrateString(
|
||||
AppPreferenceKeys.MAX_SIZE_INPUT,
|
||||
AppDefaults.MAX_SIZE_INPUT
|
||||
MAX_SIZE_INPUT,
|
||||
ScrcpyOptions.MAX_SIZE.defaultValue.toString(),
|
||||
) { value ->
|
||||
value.toIntOrNull()?.let { scrcpyOptions.maxSize.set(it) }
|
||||
}
|
||||
migrateString(
|
||||
AppPreferenceKeys.MAX_FPS_INPUT,
|
||||
AppDefaults.MAX_FPS_INPUT,
|
||||
scrcpyOptions.maxFps
|
||||
MAX_FPS_INPUT,
|
||||
ScrcpyOptions.MAX_FPS.defaultValue,
|
||||
scrcpyOptions.maxFps,
|
||||
)
|
||||
|
||||
// Encoders & Codec Options
|
||||
migrateString(
|
||||
AppPreferenceKeys.VIDEO_ENCODER,
|
||||
AppDefaults.VIDEO_ENCODER,
|
||||
scrcpyOptions.videoEncoder
|
||||
VIDEO_ENCODER,
|
||||
ScrcpyOptions.VIDEO_ENCODER.defaultValue,
|
||||
scrcpyOptions.videoEncoder,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.VIDEO_CODEC_OPTION,
|
||||
AppDefaults.VIDEO_CODEC_OPTION,
|
||||
scrcpyOptions.videoCodecOptions
|
||||
VIDEO_CODEC_OPTION,
|
||||
ScrcpyOptions.VIDEO_CODEC_OPTIONS.defaultValue,
|
||||
scrcpyOptions.videoCodecOptions,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.AUDIO_ENCODER,
|
||||
AppDefaults.AUDIO_ENCODER,
|
||||
scrcpyOptions.audioEncoder
|
||||
AUDIO_ENCODER,
|
||||
ScrcpyOptions.AUDIO_ENCODER.defaultValue,
|
||||
scrcpyOptions.audioEncoder,
|
||||
)
|
||||
migrateString(
|
||||
AppPreferenceKeys.AUDIO_CODEC_OPTION,
|
||||
AppDefaults.AUDIO_CODEC_OPTION,
|
||||
scrcpyOptions.audioCodecOptions
|
||||
AUDIO_CODEC_OPTION,
|
||||
ScrcpyOptions.AUDIO_CODEC_OPTIONS.defaultValue,
|
||||
scrcpyOptions.audioCodecOptions,
|
||||
)
|
||||
|
||||
// New Display
|
||||
val newDisplayWidth = sharedPrefs.getString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_WIDTH,
|
||||
AppDefaults.NEW_DISPLAY_WIDTH
|
||||
NEW_DISPLAY_WIDTH,
|
||||
"",
|
||||
).orEmpty()
|
||||
val newDisplayHeight = sharedPrefs.getString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_HEIGHT,
|
||||
AppDefaults.NEW_DISPLAY_HEIGHT
|
||||
NEW_DISPLAY_HEIGHT,
|
||||
"",
|
||||
).orEmpty()
|
||||
val newDisplayDpi = sharedPrefs.getString(
|
||||
AppPreferenceKeys.NEW_DISPLAY_DPI,
|
||||
AppDefaults.NEW_DISPLAY_DPI
|
||||
NEW_DISPLAY_DPI,
|
||||
"",
|
||||
).orEmpty()
|
||||
|
||||
if (newDisplayWidth.isNotBlank() && newDisplayHeight.isNotBlank()) {
|
||||
@@ -358,34 +352,33 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
|
||||
// Crop
|
||||
val cropWidth = sharedPrefs.getString(
|
||||
AppPreferenceKeys.CROP_WIDTH,
|
||||
AppDefaults.CROP_WIDTH
|
||||
CROP_WIDTH,
|
||||
"",
|
||||
).orEmpty()
|
||||
val cropHeight = sharedPrefs.getString(
|
||||
AppPreferenceKeys.CROP_HEIGHT,
|
||||
AppDefaults.CROP_HEIGHT
|
||||
CROP_HEIGHT,
|
||||
"",
|
||||
).orEmpty()
|
||||
val cropX = sharedPrefs.getString(
|
||||
AppPreferenceKeys.CROP_X,
|
||||
AppDefaults.CROP_X
|
||||
CROP_X,
|
||||
"",
|
||||
).orEmpty()
|
||||
val cropY = sharedPrefs.getString(
|
||||
AppPreferenceKeys.CROP_Y,
|
||||
AppDefaults.CROP_Y
|
||||
CROP_Y,
|
||||
"",
|
||||
).orEmpty()
|
||||
|
||||
if (cropWidth.isNotBlank() && cropHeight.isNotBlank() &&
|
||||
cropX.isNotBlank() && cropY.isNotBlank()
|
||||
if (cropWidth.isNotBlank() && cropHeight.isNotBlank()
|
||||
&& cropX.isNotBlank() && cropY.isNotBlank()
|
||||
) {
|
||||
scrcpyOptions.crop.set("${cropWidth}:${cropHeight}:${cropX}:${cropY}")
|
||||
}
|
||||
|
||||
// Audio enabled flag (convert to audio option)
|
||||
val audioEnabled = sharedPrefs.getBoolean(
|
||||
AppPreferenceKeys.AUDIO_ENABLED,
|
||||
AppDefaults.AUDIO_ENABLED
|
||||
migrateBoolean(
|
||||
AUDIO_ENABLED,
|
||||
ScrcpyOptions.AUDIO.defaultValue,
|
||||
scrcpyOptions.audio,
|
||||
)
|
||||
scrcpyOptions.audio.set(audioEnabled)
|
||||
|
||||
Log.d(TAG, "ScrcpyOptions migration completed")
|
||||
}
|
||||
@@ -398,7 +391,7 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
|
||||
// Migrate quick devices list
|
||||
val quickDevicesRaw = appSharedPrefs.getString(
|
||||
AppPreferenceKeys.QUICK_DEVICES,
|
||||
QUICK_DEVICES,
|
||||
""
|
||||
).orEmpty()
|
||||
if (quickDevicesRaw.isNotBlank()) {
|
||||
@@ -407,27 +400,27 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
|
||||
// Migrate quick connect input
|
||||
migrateString(
|
||||
AppPreferenceKeys.QUICK_CONNECT_INPUT,
|
||||
AppDefaults.QUICK_CONNECT_INPUT,
|
||||
quickDevices.quickConnectInput
|
||||
QUICK_CONNECT_INPUT,
|
||||
QuickDevices.QUICK_CONNECT_INPUT.defaultValue,
|
||||
quickDevices.quickConnectInput,
|
||||
)
|
||||
|
||||
Log.d(TAG, "QuickDevices migration completed")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 迁移 ADB 客户端数据(RSA 密钥)
|
||||
*/
|
||||
private suspend fun migrateAdbClientData() {
|
||||
val adbClientData = Storage.adbClientData
|
||||
|
||||
|
||||
// 迁移 RSA 私钥
|
||||
val privKey = sharedPrefs.getString("priv", null)
|
||||
if (privKey != null) {
|
||||
adbClientData.rsaPrivateKey.set(privKey)
|
||||
Log.d(TAG, "ADB RSA private key migrated")
|
||||
}
|
||||
|
||||
|
||||
Log.d(TAG, "AdbClientData migration completed")
|
||||
}
|
||||
|
||||
@@ -464,6 +457,15 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
settingProperty.set(value)
|
||||
}
|
||||
|
||||
private suspend fun migrateInt(
|
||||
key: String,
|
||||
defaultValue: Int,
|
||||
action: suspend (Int) -> Unit
|
||||
) {
|
||||
val value = appSharedPrefs.getInt(key, defaultValue)
|
||||
action(value)
|
||||
}
|
||||
|
||||
private suspend fun migrateBoolean(
|
||||
key: String,
|
||||
defaultValue: Boolean,
|
||||
@@ -481,4 +483,82 @@ class PreferenceMigration(private val appContext: Context) {
|
||||
val value = appSharedPrefs.getBoolean(key, defaultValue)
|
||||
action(value)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PREFS_NAME = "scrcpy_app_prefs"
|
||||
|
||||
// Devices
|
||||
const val QUICK_DEVICES = "quick_devices"
|
||||
const val QUICK_CONNECT_INPUT = "quick_connect_input"
|
||||
|
||||
const val PAIR_HOST = "pair_host"
|
||||
const val PAIR_PORT = "pair_port"
|
||||
const val PAIR_CODE = "pair_code"
|
||||
|
||||
const val AUDIO_ENABLED = "audio_enabled"
|
||||
const val AUDIO_CODEC = "audio_codec"
|
||||
const val AUDIO_BIT_RATE_INPUT = "audio_bit_rate_input"
|
||||
const val AUDIO_BIT_RATE_KBPS = "audio_bit_rate_kbps"
|
||||
const val VIDEO_CODEC = "video_codec"
|
||||
const val VIDEO_BIT_RATE_MBPS = "video_bit_rate_mbps"
|
||||
const val VIDEO_BIT_RATE_INPUT = "video_bit_rate_input"
|
||||
|
||||
const val TURN_SCREEN_OFF = "turn_screen_off"
|
||||
const val NO_CONTROL = "no_control"
|
||||
const val NO_VIDEO = "no_video"
|
||||
|
||||
const val VIDEO_SOURCE_PRESET = "video_source_preset"
|
||||
const val DISPLAY_ID = "display_id"
|
||||
|
||||
const val CAMERA_ID = "camera_id"
|
||||
const val CAMERA_FACING_PRESET = "camera_facing_preset"
|
||||
const val CAMERA_SIZE_PRESET = "camera_size_preset"
|
||||
const val CAMERA_SIZE_CUSTOM = "camera_size_custom"
|
||||
const val CAMERA_AR = "camera_ar"
|
||||
const val CAMERA_FPS = "camera_fps"
|
||||
const val CAMERA_HIGH_SPEED = "camera_high_speed"
|
||||
|
||||
const val AUDIO_SOURCE_PRESET = "audio_source_preset"
|
||||
const val AUDIO_SOURCE_CUSTOM = "audio_source_custom"
|
||||
const val AUDIO_DUP = "audio_dup"
|
||||
const val NO_AUDIO_PLAYBACK = "no_audio_playback"
|
||||
const val REQUIRE_AUDIO = "require_audio"
|
||||
|
||||
const val MAX_SIZE_INPUT = "max_size_input"
|
||||
const val MAX_FPS_INPUT = "max_fps_input"
|
||||
|
||||
const val VIDEO_ENCODER = "video_encoder"
|
||||
const val VIDEO_CODEC_OPTION = "video_codec_options"
|
||||
const val AUDIO_ENCODER = "audio_encoder"
|
||||
const val AUDIO_CODEC_OPTION = "audio_codec_options"
|
||||
|
||||
const val NEW_DISPLAY_WIDTH = "new_display_width"
|
||||
const val NEW_DISPLAY_HEIGHT = "new_display_height"
|
||||
const val NEW_DISPLAY_DPI = "new_display_dpi"
|
||||
|
||||
const val CROP_WIDTH = "crop_width"
|
||||
const val CROP_HEIGHT = "crop_height"
|
||||
const val CROP_X = "crop_x"
|
||||
const val CROP_Y = "crop_y"
|
||||
|
||||
// Settings
|
||||
const val THEME_BASE_INDEX = "theme_base_index"
|
||||
const val MONET = "monet"
|
||||
|
||||
const val FULLSCREEN_DEBUG_INFO = "fullscreen_debug_info"
|
||||
const val SHOW_FULLSCREEN_VIRTUAL_BUTTONS = "show_fullscreen_virtual_buttons"
|
||||
const val DEVICE_PREVIEW_CARD_HEIGHT_DP = "device_preview_card_height_dp"
|
||||
const val PREVIEW_VIRTUAL_BUTTON_SHOW_TEXT = "preview_virtual_button_show_text"
|
||||
const val VIRTUAL_BUTTONS_LAYOUT = "virtual_buttons_layout"
|
||||
|
||||
const val CUSTOM_SERVER_URI = "custom_server_uri"
|
||||
|
||||
const val SERVER_REMOTE_PATH = "server_remote_path"
|
||||
|
||||
const val ADB_KEY_NAME = "adb_key_name"
|
||||
const val ADB_PAIRING_AUTO_DISCOVER_ON_DIALOG_OPEN =
|
||||
"adb_pairing_auto_discover_on_dialog_open"
|
||||
const val ADB_AUTO_RECONNECT_PAIRED_DEVICE = "adb_auto_reconnect_paired_device"
|
||||
const val ADB_MDNS_LAN_DISCOVERY = "adb_mdns_lan_discovery"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user