chore: update MIUIX

This commit is contained in:
Miuzarte
2026-05-31 14:53:23 +08:00
parent a27d8638b4
commit b46a2d2d1f
14 changed files with 136 additions and 173 deletions

View File

@@ -1,5 +1,12 @@
# Change Log
## 0.4.1
- 依赖: 同步 submodule/miuix
- 改进: 补全 haptic feedback
- 新增: 设备支持多个 IP, 自动选择延迟最低的路径
- 新增: 主页允许调整卡片顺序
## 0.4.0
- 依赖: scrcpy 升级至 v4.0

View File

@@ -2,32 +2,14 @@ package io.github.miuzarte.scrcpyforandroid.pages
import android.content.Intent
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.BlendMode
@@ -40,6 +22,7 @@ import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
@@ -53,31 +36,20 @@ import io.github.miuzarte.scrcpyforandroid.R
import io.github.miuzarte.scrcpyforandroid.pages.effect.BgEffectBackground
import io.github.miuzarte.scrcpyforandroid.services.AppUpdateChecker
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
import kotlinx.coroutines.flow.onEach
import top.yukonga.miuix.kmp.basic.Card
import top.yukonga.miuix.kmp.basic.CardDefaults
import top.yukonga.miuix.kmp.basic.Icon
import top.yukonga.miuix.kmp.basic.IconButton
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
import top.yukonga.miuix.kmp.basic.Scaffold
import top.yukonga.miuix.kmp.basic.SmallTopAppBar
import top.yukonga.miuix.kmp.basic.Text
import top.yukonga.miuix.kmp.blur.BlendColorEntry
import top.yukonga.miuix.kmp.blur.BlurBlendMode
import top.yukonga.miuix.kmp.blur.BlurColors
import top.yukonga.miuix.kmp.blur.BlurDefaults
import top.yukonga.miuix.kmp.blur.isRenderEffectSupported
import top.yukonga.miuix.kmp.blur.layerBackdrop
import top.yukonga.miuix.kmp.blur.rememberLayerBackdrop
import top.yukonga.miuix.kmp.blur.textureBlur
import top.yukonga.miuix.kmp.basic.*
import top.yukonga.miuix.kmp.blur.*
import top.yukonga.miuix.kmp.preference.ArrowPreference
import top.yukonga.miuix.kmp.shader.isRenderEffectSupported
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
import top.yukonga.miuix.kmp.theme.MiuixTheme.textStyles
import java.util.Locale.getDefault
@Composable
internal fun AboutScreen() {
val haptic = LocalHapticFeedback.current
val navigator = LocalRootNavigator.current
val enableBlur = LocalEnableBlur.current
val blurBackdrop = rememberBlurBackdrop(enableBlur)
@@ -115,7 +87,12 @@ internal fun AboutScreen() {
titleColor = colorScheme.onSurface.copy(alpha = scrollProgress),
defaultWindowInsetsPadding = false,
navigationIcon = {
IconButton(onClick = navigator.pop) {
IconButton(
onClick = {
haptic.contextClick()
navigator.pop()
},
) {
Icon(
Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = stringResource(R.string.cd_back),
@@ -356,7 +333,7 @@ private fun AboutContent(
detectTapGestures(
onDoubleTap = {
isOs3Effect = !isOs3Effect
}
},
)
}
.onSizeChanged { onLogoHeightChanged(it.height) }
@@ -387,7 +364,7 @@ private fun AboutContent(
},
onClick = {
context.startActivity(
Intent(Intent.ACTION_VIEW, AppUpdateChecker.REPO_URL.toUri())
Intent(Intent.ACTION_VIEW, AppUpdateChecker.REPO_URL.toUri()),
)
},
)
@@ -407,7 +384,7 @@ private fun AboutContent(
Intent(
Intent.ACTION_VIEW,
releasesUrl.toUri(),
)
),
)
},
)
@@ -427,7 +404,7 @@ private fun AboutContent(
Intent(
Intent.ACTION_VIEW,
"https://www.apache.org/licenses/LICENSE-2.0.txt".toUri(),
)
),
)
},
)
@@ -451,7 +428,7 @@ private fun AboutContent(
Intent(
Intent.ACTION_VIEW,
repo.toUri(),
)
),
)
},
)

View File

@@ -358,7 +358,7 @@ fun FileManagerScreen(
}
if (showPathDialog) {
PathJumpDialog(
show = true,
show = showPathDialog,
path = pathInput,
onPathChange = { pathInput = it },
onDismissRequest = { showPathDialog = false },
@@ -370,7 +370,7 @@ fun FileManagerScreen(
}
if (showCreateFolderDialog) {
CreateFolderDialog(
show = true,
show = showCreateFolderDialog,
folderName = newFolderName,
onFolderNameChange = { newFolderName = it },
onDismissRequest = { showCreateFolderDialog = false },

View File

@@ -26,28 +26,15 @@ import androidx.compose.material.icons.rounded.Devices
import androidx.compose.material.icons.rounded.Folder
import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material.icons.rounded.Terminal
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.runtime.setValue
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@@ -64,44 +51,16 @@ import io.github.miuzarte.scrcpyforandroid.R
import io.github.miuzarte.scrcpyforandroid.constants.UiMotion
import io.github.miuzarte.scrcpyforandroid.nativecore.NativeAdbService
import io.github.miuzarte.scrcpyforandroid.scrcpy.Scrcpy
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
import io.github.miuzarte.scrcpyforandroid.services.AppScreenOn
import io.github.miuzarte.scrcpyforandroid.services.AppUpdateChecker
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.services.*
import io.github.miuzarte.scrcpyforandroid.storage.AppSettings
import io.github.miuzarte.scrcpyforandroid.storage.Settings
import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings
import io.github.miuzarte.scrcpyforandroid.storage.Storage.quickDevices
import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableFloatingBottomBar
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableFloatingBottomBarBlur
import io.github.miuzarte.scrcpyforandroid.ui.*
import io.github.miuzarte.scrcpyforandroid.ui.component.FloatingBottomBar
import io.github.miuzarte.scrcpyforandroid.ui.component.FloatingBottomBarItem
import io.github.miuzarte.scrcpyforandroid.ui.createThemeController
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.yukonga.miuix.kmp.basic.Icon
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
import top.yukonga.miuix.kmp.basic.NavigationBar
import top.yukonga.miuix.kmp.basic.NavigationBarItem
import top.yukonga.miuix.kmp.basic.Scaffold
import top.yukonga.miuix.kmp.basic.SnackbarHost
import top.yukonga.miuix.kmp.basic.SnackbarHostState
import top.yukonga.miuix.kmp.basic.Text
import kotlinx.coroutines.*
import top.yukonga.miuix.kmp.basic.*
import top.yukonga.miuix.kmp.theme.MiuixTheme
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
import java.io.File
@@ -147,18 +106,19 @@ private enum class MainBottomTabDestination(
Settings(labelResId = R.string.main_tab_settings, icon = Icons.Rounded.Settings);
}
sealed interface RootScreen : NavKey {
data object Home : RootScreen
data object Advanced : RootScreen
data object About : RootScreen
data object VirtualButtonOrder : RootScreen
data object FullscreenControl : RootScreen // compatibility mode
data class ScrcpyOptionRecord(val profileId: String) : RootScreen
sealed interface RootScreen: NavKey {
data object Home: RootScreen
data object Advanced: RootScreen
data object About: RootScreen
data object VirtualButtonOrder: RootScreen
data object FullscreenControl: RootScreen // compatibility mode
data class ScrcpyOptionRecord(val profileId: String): RootScreen
}
@Composable
fun MainScreen() {
// Environment
val haptic = LocalHapticFeedback.current
val context = LocalContext.current
val appContext = context.applicationContext
val activity = remember(context) { context as? Activity }
@@ -186,7 +146,8 @@ fun MainScreen() {
val tabs = remember { MainBottomTabDestination.entries }
val pagerState = rememberPagerState(
initialPage = MainBottomTabDestination.Devices.ordinal,
pageCount = { tabs.size })
pageCount = { tabs.size },
)
var selectedTabIndex by rememberSaveable {
mutableIntStateOf(MainBottomTabDestination.Devices.ordinal)
}
@@ -204,11 +165,14 @@ fun MainScreen() {
// Scroll behaviors
val devicesPageScrollBehavior = MiuixScrollBehavior(
canScroll = { currentTab == MainBottomTabDestination.Devices })
canScroll = { currentTab == MainBottomTabDestination.Devices },
)
val terminalPageScrollBehavior = MiuixScrollBehavior(
canScroll = { currentTab == MainBottomTabDestination.Terminal })
canScroll = { currentTab == MainBottomTabDestination.Terminal },
)
val settingsPageScrollBehavior = MiuixScrollBehavior(
canScroll = { currentTab == MainBottomTabDestination.Settings })
canScroll = { currentTab == MainBottomTabDestination.Settings },
)
val advancedPageScrollBehavior = MiuixScrollBehavior(
canScroll = {
when (currentRootScreen) {
@@ -217,7 +181,8 @@ fun MainScreen() {
is RootScreen.ScrcpyOptionRecord -> true
else -> false
}
})
},
)
// Navigation helpers
val rootNavigator = remember {
@@ -336,13 +301,13 @@ fun MainScreen() {
// Side-effect launchers and composition locals
val picker = rememberLauncherForActivityResult(
ActivityResultContracts.OpenDocument()
ActivityResultContracts.OpenDocument(),
) { uri: Uri? ->
if (uri == null) return@rememberLauncherForActivityResult
runCatching {
context.contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
Intent.FLAG_GRANT_READ_URI_PERMISSION,
)
}
asBundle = asBundle.copy(customServerUri = uri.toString())
@@ -353,13 +318,13 @@ fun MainScreen() {
arrayOf(
"application/java-archive",
"application/octet-stream",
"*/*"
)
"*/*",
),
)
}
}
val terminalFontDocumentPicker = rememberLauncherForActivityResult(
ActivityResultContracts.OpenDocument()
ActivityResultContracts.OpenDocument(),
) { uri: Uri? ->
if (uri == null) return@rememberLauncherForActivityResult
taskScope.launch {
@@ -392,7 +357,7 @@ fun MainScreen() {
"application/x-font-ttf",
"application/x-font-otf",
"*/*",
)
),
)
}
}
@@ -538,7 +503,10 @@ fun MainScreen() {
tabs.forEach { tab ->
NavigationBarItem(
selected = currentTab == tab,
onClick = { navigateToTab(tab) },
onClick = {
haptic.contextClick()
navigateToTab(tab)
},
icon = tab.icon,
label = stringResource(tab.labelResId),
)
@@ -577,7 +545,7 @@ fun MainScreen() {
Modifier.layerBackdrop(glassBackdrop)
} else {
Modifier
}
},
),
state = pagerState,
beyondViewportPageCount = 1,

View File

@@ -27,6 +27,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.ImeAction
@@ -47,6 +48,7 @@ import io.github.miuzarte.scrcpyforandroid.storage.Storage.scrcpyOptions
import io.github.miuzarte.scrcpyforandroid.storage.Storage.scrcpyProfiles
import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -124,6 +126,8 @@ private fun RecordPreferencesPage(
val taskScope = remember { CoroutineScope(SupervisorJob() + Dispatchers.IO) }
val currentSession by scrcpy.currentSessionState.collectAsState()
val haptic = LocalHapticFeedback.current
val soBundleShared by scrcpyOptions.bundleState.collectAsState()
val scrcpyProfilesState by scrcpyProfiles.state.collectAsState()
val sourceBundle = remember(profileId, soBundleShared, scrcpyProfilesState) {
@@ -269,6 +273,7 @@ private fun RecordPreferencesPage(
TextButton(
text = entry.value,
onClick = {
haptic.contextClick()
draftTemplate = draftTemplate.replaceSelection(entry.value)
},
insideMargin = PaddingValues(horizontal = 10.dp, vertical = 8.dp),

View File

@@ -54,7 +54,7 @@ import io.github.miuzarte.scrcpyforandroid.models.ScrcpyOptions.NewDisplay
import io.github.miuzarte.scrcpyforandroid.scaffolds.LazyColumn
import io.github.miuzarte.scrcpyforandroid.scaffolds.OverlaySpinnerWithFallback
import io.github.miuzarte.scrcpyforandroid.scaffolds.ReorderableList
import io.github.miuzarte.scrcpyforandroid.scaffolds.SuperSlider
import io.github.miuzarte.scrcpyforandroid.scaffolds.ArrowSlider
import io.github.miuzarte.scrcpyforandroid.scaffolds.SuperTextField
import io.github.miuzarte.scrcpyforandroid.scrcpy.ClientOptions
import io.github.miuzarte.scrcpyforandroid.scrcpy.Scrcpy
@@ -117,7 +117,6 @@ internal fun ScrcpyAllOptionsScreen(
val blurBackdrop = rememberBlurBackdrop(LocalEnableBlur.current)
val blurActive = blurBackdrop != null
val scope = rememberCoroutineScope()
var showProfileMenu by rememberSaveable { mutableStateOf(false) }
var showManageProfilesSheet by rememberSaveable { mutableStateOf(false) }
val qdBundleShared by quickDevices.bundleState.collectAsState()
val soBundleShared by scrcpyOptions.bundleState.collectAsState()
@@ -235,7 +234,6 @@ internal fun ScrcpyAllOptionsScreen(
text = stringResource(R.string.scrcpyopt_manage_profiles),
onClick = {
showManageProfilesSheet = true
showProfileMenu = false
},
)
)
@@ -957,7 +955,7 @@ internal fun ScrcpyAllOptionsPage(
},
enabled = soBundle.audio,
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.scrcpyopt_screen_off_timeout),
summary = "--screen-off-timeout",
value = screenOffTimeoutPresetIndex.toFloat(),
@@ -1103,7 +1101,7 @@ internal fun ScrcpyAllOptionsPage(
)
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.scrcpyopt_audio_bitrate),
summary = "--audio-bit-rate",
value = ScrcpyPresets.AudioBitRate
@@ -1148,7 +1146,7 @@ internal fun ScrcpyAllOptionsPage(
)
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.scrcpyopt_video_bitrate),
summary = "--video-bit-rate",
value = soBundle.videoBitRate / 1_000_000f,
@@ -1242,7 +1240,7 @@ internal fun ScrcpyAllOptionsPage(
)
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.scrcpyopt_min_size_alignment),
summary = "--min-size-alignment",
value = minSizeAlignmentPresetIndex.toFloat(),
@@ -1265,17 +1263,17 @@ internal fun ScrcpyAllOptionsPage(
inputFilter = { it.filter(Char::isDigit) },
inputValueRange = 1f..16f,
onInputConfirm = { raw ->
val parsed = raw.toIntOrNull() ?: return@SuperSlider
val parsed = raw.toIntOrNull() ?: return@ArrowSlider
if (parsed and (parsed - 1) != 0) {
AppRuntime.snackbar(R.string.scrcpyopt_min_size_alignment_invalid)
return@SuperSlider
return@ArrowSlider
}
soBundle = soBundle.copy(
minSizeAlignment = parsed
)
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.scrcpyopt_max_size),
summary = "--max-size",
value = maxSizePresetIndex.toFloat(),
@@ -1306,7 +1304,7 @@ internal fun ScrcpyAllOptionsPage(
)
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.scrcpyopt_max_fps),
summary = "--max-fps",
value = maxFpsPresetIndex.toFloat(),
@@ -1498,7 +1496,7 @@ internal fun ScrcpyAllOptionsPage(
.fillMaxWidth()
.padding(all = UiSpacing.Large),
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.scrcpyopt_camera_fps),
summary = "--camera-fps",
value = cameraFpsPresetIndex.toFloat(),

View File

@@ -47,7 +47,7 @@ import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
import io.github.miuzarte.scrcpyforandroid.nativecore.DirectAdbTransport
import io.github.miuzarte.scrcpyforandroid.scaffolds.LazyColumn
import io.github.miuzarte.scrcpyforandroid.scaffolds.SectionSmallTitle
import io.github.miuzarte.scrcpyforandroid.scaffolds.SuperSlider
import io.github.miuzarte.scrcpyforandroid.scaffolds.ArrowSlider
import io.github.miuzarte.scrcpyforandroid.scaffolds.SuperTextField
import io.github.miuzarte.scrcpyforandroid.scrcpy.Scrcpy
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
@@ -459,7 +459,7 @@ fun SettingsPage(
)
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.pref_title_preview_card_height),
summary = stringResource(R.string.pref_summary_preview_card_height),
value = asBundle.devicePreviewCardHeightDp.toFloat(),
@@ -598,7 +598,7 @@ fun SettingsPage(
stringResource(R.string.dock_display_on) +
stringResource(fullscreenVirtualButtonDock.directionLabelResId),
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.pref_title_virtual_button_height),
value = asBundle.fullscreenVirtualButtonHeightDp.toFloat(),
onValueChange = {
@@ -637,7 +637,7 @@ fun SettingsPage(
)
AnimatedVisibility(asBundle.showFullscreenFloatingButton) {
Column {
SuperSlider(
ArrowSlider(
title = stringResource(R.string.pref_title_floating_button_size),
value = asBundle.fullscreenFloatingButtonSizeDp.toFloat(),
onValueChange = {
@@ -662,7 +662,7 @@ fun SettingsPage(
}
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.pref_title_floating_button_bg_opacity),
value = asBundle.fullscreenFloatingButtonBackgroundAlphaPercent.toFloat(),
onValueChange = {
@@ -687,7 +687,7 @@ fun SettingsPage(
}
},
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.pref_title_floating_button_ring_opacity),
value = asBundle.fullscreenFloatingButtonRingAlphaPercent.toFloat(),
onValueChange = {
@@ -1064,7 +1064,7 @@ fun SettingsPage(
item {
SectionSmallTitle(stringResource(R.string.section_terminal))
Card {
SuperSlider(
ArrowSlider(
title = stringResource(R.string.pref_title_terminal_font_size),
summary = stringResource(R.string.pref_summary_terminal_font_size),
value = asBundle.terminalFontSizeSp,

View File

@@ -6,20 +6,13 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import io.github.miuzarte.scrcpyforandroid.R
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
@@ -29,20 +22,12 @@ import io.github.miuzarte.scrcpyforandroid.storage.Settings
import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings
import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
import io.github.miuzarte.scrcpyforandroid.widgets.VirtualButtonAction
import io.github.miuzarte.scrcpyforandroid.widgets.VirtualButtonActions
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import top.yukonga.miuix.kmp.basic.Card
import top.yukonga.miuix.kmp.basic.Icon
import top.yukonga.miuix.kmp.basic.IconButton
import top.yukonga.miuix.kmp.basic.Scaffold
import top.yukonga.miuix.kmp.basic.ScrollBehavior
import top.yukonga.miuix.kmp.basic.TopAppBar
import kotlinx.coroutines.*
import top.yukonga.miuix.kmp.basic.*
import top.yukonga.miuix.kmp.blur.layerBackdrop
import top.yukonga.miuix.kmp.preference.SwitchPreference
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
@@ -51,6 +36,7 @@ import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
internal fun VirtualButtonOrderScreen(
scrollBehavior: ScrollBehavior,
) {
val haptic = LocalHapticFeedback.current
val navigator = LocalRootNavigator.current
val blurBackdrop = rememberBlurBackdrop(LocalEnableBlur.current)
val blurActive = blurBackdrop != null
@@ -65,7 +51,12 @@ internal fun VirtualButtonOrderScreen(
if (blurActive) Color.Transparent
else colorScheme.surface,
navigationIcon = {
IconButton(onClick = navigator.pop) {
IconButton(
onClick = {
haptic.contextClick()
navigator.pop()
},
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = stringResource(R.string.cd_back),
@@ -169,10 +160,10 @@ internal fun VirtualButtonOrderPage(
}
asBundle = asBundle.copy(
virtualButtonsLayout = VirtualButtonActions
.encodeStoredLayout(buttonItems)
.encodeStoredLayout(buttonItems),
)
},
)
),
),
)
}
@@ -183,7 +174,7 @@ internal fun VirtualButtonOrderPage(
.apply { add(toIndex, removeAt(fromIndex)) }
asBundle = asBundle.copy(
virtualButtonsLayout = VirtualButtonActions
.encodeStoredLayout(buttonItems)
.encodeStoredLayout(buttonItems),
)
},
)()

View File

@@ -13,13 +13,16 @@ 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.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.res.stringResource
import io.github.miuzarte.scrcpyforandroid.R
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
import top.yukonga.miuix.kmp.basic.ButtonDefaults
import top.yukonga.miuix.kmp.basic.Slider
import top.yukonga.miuix.kmp.basic.SliderDefaults.SliderHapticEffect
import top.yukonga.miuix.kmp.basic.Text
import top.yukonga.miuix.kmp.basic.TextButton
import top.yukonga.miuix.kmp.overlay.OverlayDialog
@@ -28,19 +31,22 @@ import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
import top.yukonga.miuix.kmp.theme.MiuixTheme.textStyles
@Composable
fun SuperSlider(
fun ArrowSlider(
title: String,
summary: String? = null,
value: Float,
onValueChange: (Float) -> Unit,
valueRange: ClosedFloatingPointRange<Float>,
steps: Int,
onValueChangeFinished: (() -> Unit)? = null,
enabled: Boolean = true,
hapticEffect: SliderHapticEffect = SliderHapticEffect.Edge,
showKeyPoints: Boolean = false,
keyPoints: List<Float> = emptyList(),
magnetThreshold: Float = 0.02f,
unit: String = "",
zeroStateText: String? = null,
showUnitWhenZeroState: Boolean = false,
showKeyPoints: Boolean = false,
keyPoints: List<Float> = emptyList(),
displayFormatter: (Float) -> String = { it.toInt().toString() },
displayText: String? = null,
inputTitle: String = title,
@@ -52,6 +58,8 @@ fun SuperSlider(
inputValueRange: ClosedFloatingPointRange<Float>? = null,
onInputConfirm: (String) -> Unit,
) {
val haptic = LocalHapticFeedback.current
var showInputDialog by remember { mutableStateOf(false) }
var holdArrow by remember { mutableStateOf(false) }
@@ -59,6 +67,7 @@ fun SuperSlider(
title = title,
summary = summary,
onClick = {
haptic.contextClick()
showInputDialog = true
holdArrow = true
},
@@ -83,9 +92,12 @@ fun SuperSlider(
onValueChange = onValueChange,
valueRange = valueRange,
steps = steps,
onValueChangeFinished = onValueChangeFinished,
enabled = enabled,
hapticEffect = hapticEffect,
showKeyPoints = showKeyPoints,
keyPoints = keyPoints,
enabled = enabled,
magnetThreshold = magnetThreshold,
)
},
)
@@ -122,6 +134,8 @@ private fun SliderInputDialog(
onDismissFinished: () -> Unit,
onConfirm: (String) -> Unit,
) {
val haptic = LocalHapticFeedback.current
OverlayDialog(
show = showDialog,
title = title,
@@ -150,13 +164,17 @@ private fun SliderInputDialog(
Row(horizontalArrangement = Arrangement.SpaceBetween) {
TextButton(
text = stringResource(R.string.button_cancel),
onClick = onDismissRequest,
onClick = {
haptic.contextClick()
onDismissRequest()
},
modifier = Modifier.weight(1f),
)
Spacer(Modifier.width(20.dp))
TextButton(
text = stringResource(R.string.button_confirm),
onClick = {
haptic.contextClick()
val inputValue = text.toFloatOrNull() ?: 0f
if (inputValue >= inputValueRange.start && inputValue <= inputValueRange.endInclusive) {
onConfirm(text.trim())

View File

@@ -69,9 +69,9 @@ fun SuperTextField(
onFocusGained: (() -> Unit)? = null,
onFocusLost: (() -> Unit)? = null,
insideMargin: DpSize = DpSize(16.dp, 16.dp),
backgroundColor: Color = colorScheme.secondaryContainer,
labelColor: Color = colorScheme.onSecondaryContainer,
borderColor: Color = colorScheme.primary,
// backgroundColor: Color = colorScheme.secondaryContainer,
// labelColor: Color = colorScheme.onSecondaryContainer,
// borderColor: Color = colorScheme.primary,
textStyle: TextStyle = textStyles.main,
cursorBrush: Brush = SolidColor(colorScheme.primary),
leadingIcon: @Composable (() -> Unit)? = null,
@@ -106,9 +106,9 @@ fun SuperTextField(
keyboardActions = keyboardActions,
visualTransformation = visualTransformation,
insideMargin = insideMargin,
backgroundColor = backgroundColor,
labelColor = labelColor,
borderColor = borderColor,
// backgroundColor = backgroundColor,
// labelColor = labelColor,
// borderColor = borderColor,
textStyle = textStyle,
cursorBrush = cursorBrush,
leadingIcon = leadingIcon,

View File

@@ -9,9 +9,9 @@ import androidx.compose.ui.platform.LocalDensity
import top.yukonga.miuix.kmp.blur.BlendColorEntry
import top.yukonga.miuix.kmp.blur.BlurColors
import top.yukonga.miuix.kmp.blur.LayerBackdrop
import top.yukonga.miuix.kmp.blur.isRenderEffectSupported
import top.yukonga.miuix.kmp.blur.rememberLayerBackdrop
import top.yukonga.miuix.kmp.blur.textureBlur
import top.yukonga.miuix.kmp.shader.isRenderEffectSupported
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
val LocalEnableBlur = staticCompositionLocalOf { false }

View File

@@ -57,7 +57,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
@@ -79,7 +78,7 @@ import io.github.miuzarte.scrcpyforandroid.constants.Defaults
import io.github.miuzarte.scrcpyforandroid.constants.ScrcpyPresets
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
import io.github.miuzarte.scrcpyforandroid.models.DeviceShortcut
import io.github.miuzarte.scrcpyforandroid.scaffolds.SuperSlider
import io.github.miuzarte.scrcpyforandroid.scaffolds.ArrowSlider
import io.github.miuzarte.scrcpyforandroid.scaffolds.SuperTextField
import io.github.miuzarte.scrcpyforandroid.scrcpy.Scrcpy
import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Codec
@@ -587,7 +586,7 @@ internal fun ConfigPanel(
enabled = !sessionStarted && soBundle.audio,
)
AnimatedVisibility(audioBitRateVisibility) {
SuperSlider(
ArrowSlider(
title = stringResource(R.string.device_config_audio_bitrate),
summary = "--audio-bit-rate",
value = ScrcpyPresets.AudioBitRate
@@ -634,7 +633,7 @@ internal fun ConfigPanel(
},
enabled = !sessionStarted,
)
SuperSlider(
ArrowSlider(
title = stringResource(R.string.device_config_video_bitrate),
summary = "--video-bit-rate",
value = soBundle.videoBitRate / 1_000_000f,

View File

@@ -1,5 +1,5 @@
[versions]
agp = "9.2.0"
agp = "9.2.1"
bcpkixJdk18on = "1.83"
boringssl = "20251124"
conscryptAndroid = "2.5.3"