From e17e1badaf70a1bebcad84634ad659f4fe658499 Mon Sep 17 00:00:00 2001 From: Miuzarte <982809597@qq.com> Date: Fri, 10 Apr 2026 01:19:20 +0800 Subject: [PATCH] refactor: impl more scrcpy options; remove unused class/constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除不再需要的 `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` --- TODO.md | 16 - .../scrcpyforandroid/constants/AppDefaults.kt | 82 --- .../constants/AppPreferenceKeys.kt | 79 --- .../scrcpyforandroid/constants/Defaults.kt | 1 - .../scrcpyforandroid/pages/DeviceTabScreen.kt | 31 +- .../scrcpyforandroid/pages/MainScreen.kt | 18 - .../pages/ScrcpyAllOptionsScreen.kt | 104 +++- .../scrcpyforandroid/pages/SettingsScreen.kt | 8 - .../scrcpyforandroid/scaffolds/LazyColumn.kt | 14 +- .../scrcpyforandroid/scaffolds/SuperSlider.kt | 7 + .../services/AppSettingsStore.kt | 528 ------------------ .../scrcpyforandroid/services/EventLogger.kt | 6 +- .../scrcpyforandroid/storage/AppSettings.kt | 8 - .../storage/PreferenceMigration.kt | 374 ++++++++----- 14 files changed, 371 insertions(+), 905 deletions(-) delete mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppDefaults.kt delete mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppPreferenceKeys.kt delete mode 100644 app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppSettingsStore.kt diff --git a/TODO.md b/TODO.md index 97448bf..5581187 100644 --- a/TODO.md +++ b/TODO.md @@ -1,26 +1,10 @@ # TODO -## CURRENT - -- Refactoring - -## WIDGETS - -- `SuperTextField` Click to pop a dialog with custom notes/summary - ## PARAMS - orientation locking - `-r, --record=file.mp4` 投屏时录制到文件 Record screen to file. The format is determined by the --record-format option if set, or by the file extension. - `--record-format` 录制格式 Force recording format (mp4, mkv, m4a, mka, opus, aac, flac or wav). -- `-t, --show-touches` 显示受控机的物理触控 Enable "show touches" on start, restore the initial value on exit. It only shows physical touches (not clicks from scrcpy). -- `--no-power-on` 开始投屏时不唤醒屏幕 Do not power on the device on start. -- `--power-off-on-close` 结束投屏时息屏 Turn the device screen off when closing scrcpy. -- `--disable-screensaver` 投屏时禁用自动息屏 Disable screensaver while scrcpy is running. -- `--screen-off-timeout=seconds` 投屏过程中的息屏时间 Set the screen off timeout while scrcpy is running (restore the initial value on exit). -- `--require-audio` This option makes scrcpy fail if audio is enabled but does not work. -- `--no-vd-destroy-content` 投屏结束关闭虚拟显示器时不结束进程 Disable virtual display "destroy content on removal" flag. With this option, when the virtual display is closed, the running apps are moved to the main display rather than being destroyed. -- `--no-vd-system-decorations` Disable virtual display system decorations flag. ## FEATURES diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppDefaults.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppDefaults.kt deleted file mode 100644 index a6c1103..0000000 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppDefaults.kt +++ /dev/null @@ -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 -} diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppPreferenceKeys.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppPreferenceKeys.kt deleted file mode 100644 index 198bd21..0000000 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/AppPreferenceKeys.kt +++ /dev/null @@ -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" -} diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/Defaults.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/Defaults.kt index eecfdb6..c5cc2f0 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/Defaults.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/Defaults.kt @@ -1,6 +1,5 @@ package io.github.miuzarte.scrcpyforandroid.constants object Defaults { - const val EVENT_LOG_LINES = 512 const val ADB_PORT = 5555; } \ No newline at end of file diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabScreen.kt index 1aea49f..e54427d 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabScreen.kt @@ -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 已停止") diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/MainScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/MainScreen.kt index caaf808..82753dc 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/MainScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/MainScreen.kt @@ -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 -> diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ScrcpyAllOptionsScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ScrcpyAllOptionsScreen.kt index 8f9a5c7..9b2c488 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ScrcpyAllOptionsScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ScrcpyAllOptionsScreen.kt @@ -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 + ) + }, + ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/SettingsScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/SettingsScreen.kt index e4eb92d..9e9b533 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/SettingsScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/SettingsScreen.kt @@ -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 = "设备页预览卡高度", diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt index 4e781a0..23b3e22 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt @@ -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), diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperSlider.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperSlider.kt index fda87f9..1581228 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperSlider.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperSlider.kt @@ -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) }, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppSettingsStore.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppSettingsStore.kt deleted file mode 100644 index d9d2c1e..0000000 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppSettingsStore.kt +++ /dev/null @@ -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, - ) - } -} diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt index 84204d3..ae02188 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt @@ -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 = 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 diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt index 6eb5c96..fff143f 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt @@ -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), diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/PreferenceMigration.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/PreferenceMigration.kt index 266ddc4..47455f7 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/PreferenceMigration.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/PreferenceMigration.kt @@ -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" + } }