log panel hidden

This commit is contained in:
Miuzarte
2026-04-25 18:15:13 +08:00
parent 4cfb5b31c9
commit 84cf447b84
8 changed files with 181 additions and 76 deletions

View File

@@ -2,6 +2,10 @@
~~什么我居然开始写更新日志了~~
## 0.2.7
- 新增: 日志框隐藏
## 0.2.6
- 新增: 全屏下将系统返回手势映射为发送返回按键

View File

@@ -118,6 +118,9 @@
5. 横屏模式对左撇子不太友好
- 右上角有按钮可以对调方向
6. MIUI 虚拟屏没有桌面 / 虚拟屏白屏
- 装个第三方桌面
## 构建
- JDK 17+

View File

@@ -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)

View File

@@ -1344,7 +1344,7 @@ internal fun DeviceTabPage(
@Composable
fun LogsSection() {
if (EventLogger.hasLogs()) {
if (!asBundle.hideDeviceLogs && EventLogger.hasLogs()) {
SectionSmallTitle("日志")
Card {
TextField(

View File

@@ -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()
}
}

View File

@@ -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 {

View File

@@ -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(
)
}
}
}
}

View File

@@ -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<Bundle> = 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)