From 84cf447b84d397ea944a048d28242bf0e6af2852 Mon Sep 17 00:00:00 2001 From: Miuzarte <982809597@qq.com> Date: Sat, 25 Apr 2026 18:15:13 +0800 Subject: [PATCH] log panel hidden --- CHANGELOG.md | 4 + README.md | 3 + app/build.gradle.kts | 16 +- .../scrcpyforandroid/pages/DeviceTabScreen.kt | 2 +- .../scrcpyforandroid/pages/MainScreen.kt | 4 + .../pages/ScrcpyAllOptionsScreen.kt | 2 +- .../scrcpyforandroid/pages/SettingsScreen.kt | 190 ++++++++++++------ .../scrcpyforandroid/storage/AppSettings.kt | 36 +++- 8 files changed, 181 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09ead88..9a54139 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ~~什么我居然开始写更新日志了~~ +## 0.2.7 + +- 新增: 日志框隐藏 + ## 0.2.6 - 新增: 全屏下将系统返回手势映射为发送返回按键 diff --git a/README.md b/README.md index 7c2fcb9..eb0956b 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,9 @@ 5. 横屏模式对左撇子不太友好 - 右上角有按钮可以对调方向 +6. MIUI 虚拟屏没有桌面 / 虚拟屏白屏 + - 装个第三方桌面 + ## 构建 - JDK 17+ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ef3cb1d..91fa0cc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,6 +13,8 @@ val configuredAbiList = (project.findProperty("abiList") as String?) ?.filter { it.isNotEmpty() } ?.ifEmpty { null } ?: defaultAbiList +val buildUniversalApk = configuredAbiList.size > 1 +val singleAbi = configuredAbiList.singleOrNull() android { namespace = "io.github.miuzarte.scrcpyforandroid" @@ -74,10 +76,10 @@ android { splits { abi { - isEnable = true + isEnable = buildUniversalApk reset() include(*configuredAbiList.toTypedArray()) - isUniversalApk = true + isUniversalApk = buildUniversalApk } } @@ -111,6 +113,16 @@ android { ndkVersion = "29.0.14206865" } +androidComponents { + onVariants { variant -> + singleAbi?.let { abi -> + variant.outputs.forEach { output -> + output.outputFileName.set("app-$abi-${variant.name}.apk") + } + } + } +} + dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) 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 16a84a0..37d08ca 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 @@ -1344,7 +1344,7 @@ internal fun DeviceTabPage( @Composable fun LogsSection() { - if (EventLogger.hasLogs()) { + if (!asBundle.hideDeviceLogs && EventLogger.hasLogs()) { SectionSmallTitle("日志") Card { TextField( 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 ff1fceb..64c4146 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 @@ -68,6 +68,7 @@ import io.github.miuzarte.scrcpyforandroid.services.ConnectionController import io.github.miuzarte.scrcpyforandroid.services.ConnectionStateStore import io.github.miuzarte.scrcpyforandroid.services.DeviceAdbAutoReconnectManager import io.github.miuzarte.scrcpyforandroid.services.DeviceAdbConnectionCoordinator +import io.github.miuzarte.scrcpyforandroid.services.EventLogger import io.github.miuzarte.scrcpyforandroid.services.LocalSnackbarController import io.github.miuzarte.scrcpyforandroid.services.SnackbarController import io.github.miuzarte.scrcpyforandroid.storage.AppSettings @@ -451,6 +452,9 @@ fun MainScreen() { runCatching { scrcpy.stop() } runCatching { NativeAdbService.disconnect() } } + if (asBundle.clearLogsOnExit) { + EventLogger.clearLogs() + } activity?.finish() } } 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 9cdb893..face8ad 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 @@ -746,7 +746,7 @@ internal fun ScrcpyAllOptionsPage( } val apps = remember(scrcpy.listings.apps, listRefreshVersion) { - scrcpy.listings.apps.sortedBy { it.packageName } + scrcpy.listings.apps // .sortedBy { it.packageName } } val appDropdownItems by remember(apps, listRefreshVersion) { derivedStateOf { 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 d794e88..01b1e3c 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 @@ -1,5 +1,6 @@ package io.github.miuzarte.scrcpyforandroid.pages +import android.content.Context import android.content.Intent import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Arrangement @@ -81,14 +82,14 @@ private const val TERMINAL_FONT_RELATIVE_PATH = "terminal/font.ttf" private val monetPaletteStyleOptions = ThemePaletteStyle.entries.map { it.name } private val monetColorSpecOptions = ThemeColorSpec.entries.map { it.name } -private fun terminalFontFile(context: android.content.Context): File { - return File(context.filesDir, TERMINAL_FONT_RELATIVE_PATH) -} - -private fun clearTerminalFont(context: android.content.Context): Boolean { - val target = terminalFontFile(context) - return target.exists() && target.delete() -} +suspend fun clearTerminalFont(context: Context) = + withContext(Dispatchers.IO) { + val target = File( + context.filesDir, + TERMINAL_FONT_RELATIVE_PATH, + ) + target.exists() && target.delete() + } @Composable fun SettingsScreen( @@ -135,7 +136,6 @@ fun SettingsPage( onOpenReorderDevices: () -> Unit, ) { val context = LocalContext.current - val appContext = context.applicationContext val updateState by AppUpdateChecker.state.collectAsState() val taskScope = remember { CoroutineScope(SupervisorJob() + Dispatchers.IO) } @@ -235,7 +235,9 @@ fun SettingsPage( selectedIndex = asBundle.themeBaseIndex .coerceIn(0, ThemeModes.baseOptions.lastIndex), onSelectedIndexChange = { - asBundle = asBundle.copy(themeBaseIndex = it) + asBundle = asBundle.copy( + themeBaseIndex = it + ) }, ) SwitchPreference( @@ -243,20 +245,26 @@ fun SettingsPage( summary = "开启后使用 Monet 动态配色", checked = asBundle.monet, onCheckedChange = { - asBundle = asBundle.copy(monet = it) + asBundle = asBundle.copy( + monet = it + ) }, ) AnimatedVisibility(asBundle.monet) { - OverlayDropdownPreference( - title = "Monet Key Color", - summary = "设置 Monet 强调色", - items = MonetKeyColorOptions, - selectedIndex = asBundle.monetSeedIndex - .coerceIn(0, MonetKeyColorOptions.lastIndex), - onSelectedIndexChange = { - asBundle = asBundle.copy(monetSeedIndex = it) - }, - ) + Column { + OverlayDropdownPreference( + title = "Monet Key Color", + summary = "设置 Monet 强调色", + items = MonetKeyColorOptions, + selectedIndex = asBundle.monetSeedIndex + .coerceIn(0, MonetKeyColorOptions.lastIndex), + onSelectedIndexChange = { + asBundle = asBundle.copy( + monetSeedIndex = it + ) + }, + ) + } } AnimatedVisibility(asBundle.monet && asBundle.monetSeedIndex > 0) { Column { @@ -267,7 +275,9 @@ fun SettingsPage( selectedIndex = asBundle.monetPaletteStyle .coerceIn(0, monetPaletteStyleOptions.lastIndex), onSelectedIndexChange = { - asBundle = asBundle.copy(monetPaletteStyle = it) + asBundle = asBundle.copy( + monetPaletteStyle = it + ) }, ) OverlayDropdownPreference( @@ -277,7 +287,9 @@ fun SettingsPage( selectedIndex = asBundle.monetColorSpec .coerceIn(0, monetColorSpecOptions.lastIndex), onSelectedIndexChange = { - asBundle = asBundle.copy(monetColorSpec = it) + asBundle = asBundle.copy( + monetColorSpec = it + ) }, ) } @@ -287,7 +299,9 @@ fun SettingsPage( summary = "启用顶栏和底栏的模糊效果", checked = asBundle.blur, onCheckedChange = { - asBundle = asBundle.copy(blur = it) + asBundle = asBundle.copy( + blur = it + ) } ) SwitchPreference( @@ -295,25 +309,34 @@ fun SettingsPage( summary = "使用 Apple 风格的悬浮底栏", checked = asBundle.floatingBottomBar, onCheckedChange = { - asBundle = asBundle.copy(floatingBottomBar = it) + asBundle = asBundle.copy( + floatingBottomBar = it + ) } ) - AnimatedVisibility(asBundle.floatingBottomBar) { - SwitchPreference( - title = "液态玻璃", - summary = "启用悬浮底栏的液态玻璃效果", - checked = asBundle.floatingBottomBarBlur, - onCheckedChange = { - asBundle = asBundle.copy(floatingBottomBarBlur = it) - } - ) + AnimatedVisibility(asBundle.floatingBottomBar && asBundle.blur) { + Column { + SwitchPreference( + title = "液态玻璃", + summary = "启用悬浮底栏的液态玻璃效果", + checked = asBundle.floatingBottomBar && asBundle.blur + && asBundle.floatingBottomBarBlur, + onCheckedChange = { + asBundle = asBundle.copy( + floatingBottomBarBlur = it + ) + } + ) + } } SwitchPreference( title = "平滑圆角", summary = "启用全局平滑圆角效果", checked = asBundle.smoothCorner, onCheckedChange = { - asBundle = asBundle.copy(smoothCorner = it) + asBundle = asBundle.copy( + smoothCorner = it + ) } ) } @@ -330,19 +353,23 @@ fun SettingsPage( 推荐配合 RAW PCM 编解码 修改后建议划卡重启应用 """.trimIndent(), + enabled = !isScrcpyStreaming, checked = asBundle.lowLatency, onCheckedChange = { if (!isScrcpyStreaming) - asBundle = asBundle.copy(lowLatency = it) + asBundle = asBundle.copy( + lowLatency = it + ) }, - enabled = !isScrcpyStreaming, ) SwitchPreference( title = "启用调试信息", summary = "在全屏界面悬浮显示分辨率、帧率和触点信息", checked = asBundle.fullscreenDebugInfo, onCheckedChange = { - asBundle = asBundle.copy(fullscreenDebugInfo = it) + asBundle = asBundle.copy( + fullscreenDebugInfo = it + ) }, ) SwitchPreference( @@ -350,7 +377,9 @@ fun SettingsPage( summary = "启用后设备页仅保留更多参数、所有应用、最近任务和启动/停止按钮", checked = asBundle.hideSimpleConfigItems, onCheckedChange = { - asBundle = asBundle.copy(hideSimpleConfigItems = it) + asBundle = asBundle.copy( + hideSimpleConfigItems = it + ) }, ) SuperSlider( @@ -395,6 +424,27 @@ fun SettingsPage( context.startActivity(LockscreenPasswordActivity.createIntent(context)) }, ) + SwitchPreference( + title = "实时同步剪贴板到受控机", + summary = + """ + 本机剪贴板更新后会自动同步到受控机 + 禁用后需要使用虚拟按钮中的粘贴才能粘贴本机内容 + MIUI 完全不允许后台监听剪贴板,因此该选项在小米设备上可能无效 + """.trimIndent(), + checked = asBundle.realtimeClipboardSyncToDevice, + onCheckedChange = { + asBundle = asBundle.copy( + realtimeClipboardSyncToDevice = it + ) + }, + ) + } + } + + item { + SectionSmallTitle("全屏") + Card { SwitchPreference( title = "全屏时不跟随系统旋转锁定", summary = "启用后使用传感器方向,忽略系统自动旋转锁定状态", @@ -420,11 +470,13 @@ fun SettingsPage( }, ) SwitchPreference( - title = "全屏显示虚拟按钮", + title = "全屏时显示虚拟按钮", summary = "在全屏控制页中显示返回键、主页键等虚拟按钮", checked = asBundle.showFullscreenVirtualButtons, onCheckedChange = { - asBundle = asBundle.copy(showFullscreenVirtualButtons = it) + asBundle = asBundle.copy( + showFullscreenVirtualButtons = it + ) }, ) AnimatedVisibility(asBundle.showFullscreenVirtualButtons) { @@ -491,11 +543,13 @@ fun SettingsPage( } } SwitchPreference( - title = "全屏显示悬浮球", + title = "全屏时显示悬浮球", summary = "在全屏控制页中显示可拖动的悬浮球,点击后弹出完整虚拟按键菜单", checked = asBundle.showFullscreenFloatingButton, onCheckedChange = { - asBundle = asBundle.copy(showFullscreenFloatingButton = it) + asBundle = asBundle.copy( + showFullscreenFloatingButton = it + ) }, ) AnimatedVisibility(asBundle.showFullscreenFloatingButton) { @@ -577,21 +631,6 @@ fun SettingsPage( ) } } - SwitchPreference( - title = "实时同步剪贴板到受控机", - summary = - """ - 本机剪贴板更新后会自动同步到受控机 - 禁用后需要使用虚拟按钮中的粘贴才能粘贴本机内容 - MIUI 完全不允许后台监听剪贴板,因此该选项在小米设备上可能无效 - """.trimIndent(), - checked = asBundle.realtimeClipboardSyncToDevice, - onCheckedChange = { - asBundle = asBundle.copy( - realtimeClipboardSyncToDevice = it - ) - }, - ) } } @@ -862,16 +901,12 @@ fun SettingsPage( useLabelAsPlaceholder = true, modifier = Modifier.fillMaxWidth(), trailingIcon = { - Row( - modifier = Modifier.padding(end = UiSpacing.Medium), - ) { + Row(modifier = Modifier.padding(end = UiSpacing.Medium)) { if (asBundle.terminalFontDisplayName.isNotBlank()) { IconButton( onClick = { scope.launch { - val cleared = withContext(Dispatchers.IO) { - clearTerminalFont(context) - } + val cleared = clearTerminalFont(context) asBundle = asBundle.copy( terminalFontDisplayName = "" ) @@ -902,6 +937,32 @@ fun SettingsPage( } } + item { + SectionSmallTitle("杂项") + Card { + SwitchPreference( + title = "退出应用时清除日志", + summary = "双击返回退出应用时清除日志", + checked = asBundle.clearLogsOnExit, + onCheckedChange = { + asBundle = asBundle.copy( + clearLogsOnExit = it + ) + }, + ) + SwitchPreference( + title = "隐藏设备页日志框", + summary = "隐藏设备页最下方的日志框", + checked = asBundle.hideDeviceLogs, + onCheckedChange = { + asBundle = asBundle.copy( + hideDeviceLogs = it + ) + }, + ) + } + } + item { SectionSmallTitle("") Card { @@ -912,6 +973,5 @@ fun SettingsPage( ) } } - } } 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 9c8b187..1dff42a 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 @@ -122,6 +122,12 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { intPreferencesKey("device_preview_card_height_dp"), 1080 / 3, ) + val REALTIME_CLIPBOARD_SYNC_TO_DEVICE = Pair( + booleanPreferencesKey("realtime_clipboard_sync_to_device"), + true, + ) + + // Fullscreen val FULLSCREEN_CONTROL_IGNORE_SYSTEM_ROTATION_LOCK = Pair( booleanPreferencesKey("fullscreen_control_ignore_system_rotation_lock"), true, @@ -158,10 +164,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { intPreferencesKey("fullscreen_floating_button_ring_alpha_percent"), 100, ) - val REALTIME_CLIPBOARD_SYNC_TO_DEVICE = Pair( - booleanPreferencesKey("realtime_clipboard_sync_to_device"), - true, - ) val FULLSCREEN_FLOATING_BUTTON_X_FRACTION = Pair( floatPreferencesKey("fullscreen_floating_button_x_fraction"), @@ -262,6 +264,14 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { longPreferencesKey("last_update_check_at"), 0L, ) + val CLEAR_LOGS_ON_EXIT = Pair( + booleanPreferencesKey("clear_logs_on_exit"), + true, + ) + val HIDE_DEVICE_LOGS = Pair( + booleanPreferencesKey("hide_device_logs"), + false, + ) } @Parcelize @@ -282,6 +292,9 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { val fullscreenDebugInfo: Boolean, val hideSimpleConfigItems: Boolean, val devicePreviewCardHeightDp: Int, + val realtimeClipboardSyncToDevice: Boolean, + + // Fullscreen val fullscreenControlIgnoreSystemRotationLock: Boolean, val fullscreenControlBackToDevice: Boolean, val showFullscreenVirtualButtons: Boolean, @@ -291,7 +304,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { val fullscreenFloatingButtonSizeDp: Int, val fullscreenFloatingButtonBackgroundAlphaPercent: Int, val fullscreenFloatingButtonRingAlphaPercent: Int, - val realtimeClipboardSyncToDevice: Boolean, val fullscreenFloatingButtonXFraction: Float, val fullscreenFloatingButtonYFraction: Float, @@ -320,6 +332,8 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { val fileManagerSortBy: String, val fileManagerSortDescending: Boolean, val lastUpdateCheckAt: Long, + val clearLogsOnExit: Boolean, + val hideDeviceLogs: Boolean, ) : Parcelable { } @@ -340,6 +354,9 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { bundleField(FULLSCREEN_DEBUG_INFO) { it.fullscreenDebugInfo }, bundleField(HIDE_SIMPLE_CONFIG_ITEMS) { it.hideSimpleConfigItems }, bundleField(DEVICE_PREVIEW_CARD_HEIGHT_DP) { it.devicePreviewCardHeightDp }, + bundleField(REALTIME_CLIPBOARD_SYNC_TO_DEVICE) { it.realtimeClipboardSyncToDevice }, + + // Fullscreen bundleField(FULLSCREEN_CONTROL_IGNORE_SYSTEM_ROTATION_LOCK) { it.fullscreenControlIgnoreSystemRotationLock }, bundleField(FULLSCREEN_CONTROL_BACK_TO_DEVICE) { it.fullscreenControlBackToDevice }, bundleField(SHOW_FULLSCREEN_VIRTUAL_BUTTONS) { it.showFullscreenVirtualButtons }, @@ -349,7 +366,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { bundleField(FULLSCREEN_FLOATING_BUTTON_SIZE_DP) { it.fullscreenFloatingButtonSizeDp }, bundleField(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT) { it.fullscreenFloatingButtonBackgroundAlphaPercent }, bundleField(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT) { it.fullscreenFloatingButtonRingAlphaPercent }, - bundleField(REALTIME_CLIPBOARD_SYNC_TO_DEVICE) { it.realtimeClipboardSyncToDevice }, bundleField(FULLSCREEN_FLOATING_BUTTON_X_FRACTION) { it.fullscreenFloatingButtonXFraction }, bundleField(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION) { it.fullscreenFloatingButtonYFraction }, @@ -378,6 +394,8 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { bundleField(FILE_MANAGER_SORT_BY) { it.fileManagerSortBy }, bundleField(FILE_MANAGER_SORT_DESCENDING) { it.fileManagerSortDescending }, bundleField(LAST_UPDATE_CHECK_AT) { it.lastUpdateCheckAt }, + bundleField(CLEAR_LOGS_ON_EXIT) { it.clearLogsOnExit }, + bundleField(HIDE_DEVICE_LOGS) { it.hideDeviceLogs }, ) val bundleState: StateFlow = createBundleState(::bundleFromPreferences) @@ -399,6 +417,9 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { fullscreenDebugInfo = preferences.read(FULLSCREEN_DEBUG_INFO), hideSimpleConfigItems = preferences.read(HIDE_SIMPLE_CONFIG_ITEMS), devicePreviewCardHeightDp = preferences.read(DEVICE_PREVIEW_CARD_HEIGHT_DP), + realtimeClipboardSyncToDevice = preferences.read(REALTIME_CLIPBOARD_SYNC_TO_DEVICE), + + // Fullscreen fullscreenControlIgnoreSystemRotationLock = preferences.read(FULLSCREEN_CONTROL_IGNORE_SYSTEM_ROTATION_LOCK), fullscreenControlBackToDevice = preferences.read(FULLSCREEN_CONTROL_BACK_TO_DEVICE), @@ -411,7 +432,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { preferences.read(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT), fullscreenFloatingButtonRingAlphaPercent = preferences.read(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT), - realtimeClipboardSyncToDevice = preferences.read(REALTIME_CLIPBOARD_SYNC_TO_DEVICE), fullscreenFloatingButtonXFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_X_FRACTION), fullscreenFloatingButtonYFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION), @@ -440,6 +460,8 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { fileManagerSortBy = preferences.read(FILE_MANAGER_SORT_BY), fileManagerSortDescending = preferences.read(FILE_MANAGER_SORT_DESCENDING), lastUpdateCheckAt = preferences.read(LAST_UPDATE_CHECK_AT), + clearLogsOnExit = preferences.read(CLEAR_LOGS_ON_EXIT), + hideDeviceLogs = preferences.read(HIDE_DEVICE_LOGS), ) suspend fun loadBundle() = loadBundle(::bundleFromPreferences)