chore: update MIUIX
This commit is contained in:
@@ -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(),
|
||||
)
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
},
|
||||
)()
|
||||
|
||||
@@ -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())
|
||||
@@ -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,
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user