feat: language select manually
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
- 新增: 语言选择
|
||||||
|
- 改进: zh-rCN 重命名至 zh 实现繁中回退简中
|
||||||
|
- 依赖: miuix 同步至最新提交
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
- 修复: 部分设备 (ColorOS) 在拉起输入法后,返回事件会经由输入法最终被发往受控机
|
- 修复: 部分设备 (ColorOS) 在拉起输入法后,返回事件会经由输入法最终被发往受控机
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ android {
|
|||||||
applicationId = "io.github.miuzarte.scrcpyforandroid"
|
applicationId = "io.github.miuzarte.scrcpyforandroid"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 37
|
targetSdk = 37
|
||||||
versionCode = 28
|
versionCode = 29
|
||||||
versionName = "0.3.2"
|
versionName = "0.3.3"
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.view.WindowManager
|
|||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -37,13 +36,14 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
||||||
import io.github.miuzarte.scrcpyforandroid.password.BiometricGate
|
import io.github.miuzarte.scrcpyforandroid.password.BiometricGate
|
||||||
import io.github.miuzarte.scrcpyforandroid.password.PasswordCreatedState
|
import io.github.miuzarte.scrcpyforandroid.password.PasswordCreatedState
|
||||||
@@ -66,19 +66,15 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.Card
|
import top.yukonga.miuix.kmp.basic.Card
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownEntry
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownItem
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.IconButton
|
import top.yukonga.miuix.kmp.basic.IconButton
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
|
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
|
||||||
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
|
||||||
import top.yukonga.miuix.kmp.basic.Scaffold
|
import top.yukonga.miuix.kmp.basic.Scaffold
|
||||||
import top.yukonga.miuix.kmp.basic.ScrollBehavior
|
import top.yukonga.miuix.kmp.basic.ScrollBehavior
|
||||||
import top.yukonga.miuix.kmp.basic.SnackbarHost
|
import top.yukonga.miuix.kmp.basic.SnackbarHost
|
||||||
import top.yukonga.miuix.kmp.basic.SnackbarHostState
|
import top.yukonga.miuix.kmp.basic.SnackbarHostState
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerEntry
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerItemImpl
|
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
import top.yukonga.miuix.kmp.basic.TextButton
|
import top.yukonga.miuix.kmp.basic.TextButton
|
||||||
import top.yukonga.miuix.kmp.basic.TextField
|
import top.yukonga.miuix.kmp.basic.TextField
|
||||||
@@ -88,9 +84,9 @@ import top.yukonga.miuix.kmp.icon.MiuixIcons
|
|||||||
import top.yukonga.miuix.kmp.icon.extended.Close
|
import top.yukonga.miuix.kmp.icon.extended.Close
|
||||||
import top.yukonga.miuix.kmp.icon.extended.More
|
import top.yukonga.miuix.kmp.icon.extended.More
|
||||||
import top.yukonga.miuix.kmp.icon.extended.Ok
|
import top.yukonga.miuix.kmp.icon.extended.Ok
|
||||||
|
import top.yukonga.miuix.kmp.menu.OverlayIconDropdownMenu
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayDialog
|
import top.yukonga.miuix.kmp.overlay.OverlayDialog
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayListPopup
|
|
||||||
import top.yukonga.miuix.kmp.preference.ArrowPreference
|
import top.yukonga.miuix.kmp.preference.ArrowPreference
|
||||||
import top.yukonga.miuix.kmp.preference.SwitchPreference
|
import top.yukonga.miuix.kmp.preference.SwitchPreference
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
@@ -124,7 +120,6 @@ class LockscreenPasswordActivity : FragmentActivity() {
|
|||||||
}
|
}
|
||||||
MiuixTheme(
|
MiuixTheme(
|
||||||
controller = themeController,
|
controller = themeController,
|
||||||
smoothRounding = asBundle.smoothCorner,
|
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalSnackbarController provides snackbarController,
|
LocalSnackbarController provides snackbarController,
|
||||||
@@ -181,7 +176,6 @@ private fun LockscreenPasswordScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val entries by PasswordRepository.entriesState.collectAsState()
|
val entries by PasswordRepository.entriesState.collectAsState()
|
||||||
var showMenu by rememberSaveable { mutableStateOf(false) }
|
|
||||||
var pendingCreate by rememberSaveable { mutableStateOf(false) }
|
var pendingCreate by rememberSaveable { mutableStateOf(false) }
|
||||||
var showRiskDialog by rememberSaveable { mutableStateOf(!BiometricGate.isDeviceSecure()) }
|
var showRiskDialog by rememberSaveable { mutableStateOf(!BiometricGate.isDeviceSecure()) }
|
||||||
var showDisableDialog by rememberSaveable { mutableStateOf(false) }
|
var showDisableDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
@@ -191,10 +185,10 @@ private fun LockscreenPasswordScreen(
|
|||||||
var editorInitialName by rememberSaveable { mutableStateOf("") }
|
var editorInitialName by rememberSaveable { mutableStateOf("") }
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
val observer = androidx.lifecycle.LifecycleEventObserver { _, event ->
|
val observer = LifecycleEventObserver { _, event ->
|
||||||
if (
|
if (
|
||||||
event == androidx.lifecycle.Lifecycle.Event.ON_PAUSE ||
|
event == Lifecycle.Event.ON_PAUSE ||
|
||||||
event == androidx.lifecycle.Lifecycle.Event.ON_STOP
|
event == Lifecycle.Event.ON_STOP
|
||||||
) {
|
) {
|
||||||
editorInitialName = ""
|
editorInitialName = ""
|
||||||
}
|
}
|
||||||
@@ -205,8 +199,8 @@ private fun LockscreenPasswordScreen(
|
|||||||
|
|
||||||
val textCreate = stringResource(R.string.password_authenticate_create)
|
val textCreate = stringResource(R.string.password_authenticate_create)
|
||||||
val textSubtitle = stringResource(R.string.password_authenticate_subtitle)
|
val textSubtitle = stringResource(R.string.password_authenticate_subtitle)
|
||||||
LaunchedEffect(pendingCreate, showMenu) {
|
LaunchedEffect(pendingCreate) {
|
||||||
if (!pendingCreate || showMenu) return@LaunchedEffect
|
if (!pendingCreate) return@LaunchedEffect
|
||||||
if (asBundle.passwordRequireAuth) {
|
if (asBundle.passwordRequireAuth) {
|
||||||
val ok = BiometricGate.authenticate(
|
val ok = BiometricGate.authenticate(
|
||||||
activity = activity,
|
activity = activity,
|
||||||
@@ -246,37 +240,23 @@ private fun LockscreenPasswordScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
Box {
|
val textCreateNew = stringResource(R.string.password_create_new)
|
||||||
IconButton(
|
OverlayIconDropdownMenu(
|
||||||
onClick = { showMenu = true },
|
entry = DropdownEntry(
|
||||||
) {
|
items = listOf(
|
||||||
Icon(
|
DropdownItem(
|
||||||
imageVector = MiuixIcons.More,
|
text = textCreateNew,
|
||||||
contentDescription = stringResource(R.string.cd_more),
|
onClick = {
|
||||||
)
|
|
||||||
}
|
|
||||||
val textCreateNew = stringResource(R.string.password_create_new)
|
|
||||||
OverlayListPopup(
|
|
||||||
show = showMenu,
|
|
||||||
popupPositionProvider = ListPopupDefaults.ContextMenuPositionProvider,
|
|
||||||
alignment = PopupPositionProvider.Align.TopEnd,
|
|
||||||
onDismissRequest = { showMenu = false },
|
|
||||||
) {
|
|
||||||
ListPopupColumn {
|
|
||||||
SpinnerItemImpl(
|
|
||||||
entry = SpinnerEntry(title = textCreateNew),
|
|
||||||
entryCount = 1,
|
|
||||||
isSelected = false,
|
|
||||||
index = 0,
|
|
||||||
spinnerColors = SpinnerDefaults.spinnerColors(),
|
|
||||||
dialogMode = false,
|
|
||||||
onSelectedIndexChange = {
|
|
||||||
showMenu = false
|
|
||||||
pendingCreate = true
|
pendingCreate = true
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = MiuixIcons.More,
|
||||||
|
contentDescription = stringResource(R.string.cd_more),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package io.github.miuzarte.scrcpyforandroid
|
package io.github.miuzarte.scrcpyforandroid
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.core.content.edit
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import io.github.miuzarte.scrcpyforandroid.pages.MainScreen
|
import io.github.miuzarte.scrcpyforandroid.pages.MainScreen
|
||||||
import io.github.miuzarte.scrcpyforandroid.password.BiometricGate
|
import io.github.miuzarte.scrcpyforandroid.password.BiometricGate
|
||||||
@@ -13,10 +16,26 @@ import io.github.miuzarte.scrcpyforandroid.password.PasswordRepository
|
|||||||
import io.github.miuzarte.scrcpyforandroid.password.hasAuthenticatedOrigin
|
import io.github.miuzarte.scrcpyforandroid.password.hasAuthenticatedOrigin
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.AppScreenOn
|
import io.github.miuzarte.scrcpyforandroid.services.AppScreenOn
|
||||||
|
import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
// 生物认证需要 FragmentActivity
|
// 生物认证需要 FragmentActivity
|
||||||
class MainActivity : FragmentActivity() {
|
class MainActivity : FragmentActivity() {
|
||||||
|
|
||||||
|
override fun attachBaseContext(newBase: Context) {
|
||||||
|
val languageTag = getAppLanguageTag(newBase)
|
||||||
|
val wrappedContext =
|
||||||
|
if (languageTag.isNotEmpty()) {
|
||||||
|
val config = Configuration(newBase.resources.configuration)
|
||||||
|
config.setLocale(Locale.forLanguageTag(languageTag))
|
||||||
|
newBase.createConfigurationContext(config)
|
||||||
|
} else {
|
||||||
|
newBase
|
||||||
|
}
|
||||||
|
super.attachBaseContext(wrappedContext)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
applyMainOrientationPolicy()
|
applyMainOrientationPolicy()
|
||||||
@@ -27,6 +46,13 @@ class MainActivity : FragmentActivity() {
|
|||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
PasswordRepository.refresh()
|
PasswordRepository.refresh()
|
||||||
|
val cached = getAppLanguageTag(applicationContext)
|
||||||
|
if (cached.isNotEmpty()) {
|
||||||
|
val bundle = appSettings.loadBundle()
|
||||||
|
if (bundle.languageTag != cached) {
|
||||||
|
appSettings.updateBundle { it.copy(languageTag = cached) }
|
||||||
|
}
|
||||||
|
}
|
||||||
// 认证不可用时, 清除经认证创建的密码
|
// 认证不可用时, 清除经认证创建的密码
|
||||||
if (!BiometricGate.canAuthenticate()) {
|
if (!BiometricGate.canAuthenticate()) {
|
||||||
PasswordRepository.getAll()
|
PasswordRepository.getAll()
|
||||||
@@ -75,7 +101,18 @@ class MainActivity : FragmentActivity() {
|
|||||||
return maxOf(width, height).toFloat() / minOf(width, height).toFloat()
|
return maxOf(width, height).toFloat() / minOf(width, height).toFloat()
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
internal companion object {
|
||||||
private const val PHONE_LANDSCAPE_LOCK_ASPECT_RATIO = 16f / 9f
|
private const val PHONE_LANDSCAPE_LOCK_ASPECT_RATIO = 16f / 9f
|
||||||
|
|
||||||
|
private const val LOCALE_PREFS = "locale_cache"
|
||||||
|
private const val KEY_LANGUAGE_TAG = "language_tag"
|
||||||
|
|
||||||
|
fun getAppLanguageTag(context: Context) =
|
||||||
|
context.getSharedPreferences(LOCALE_PREFS, MODE_PRIVATE)
|
||||||
|
.getString(KEY_LANGUAGE_TAG, "") ?: ""
|
||||||
|
|
||||||
|
fun setAppLanguageTag(context: Context, languageTag: String) =
|
||||||
|
context.getSharedPreferences(LOCALE_PREFS, MODE_PRIVATE)
|
||||||
|
.edit { putString(KEY_LANGUAGE_TAG, languageTag) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import top.yukonga.miuix.kmp.basic.BasicComponent
|
|||||||
import top.yukonga.miuix.kmp.basic.BasicComponentColors
|
import top.yukonga.miuix.kmp.basic.BasicComponentColors
|
||||||
import top.yukonga.miuix.kmp.basic.BasicComponentDefaults
|
import top.yukonga.miuix.kmp.basic.BasicComponentDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.DropdownArrowEndAction
|
import top.yukonga.miuix.kmp.basic.DropdownArrowEndAction
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownColors
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
||||||
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerColors
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayListPopup
|
import top.yukonga.miuix.kmp.overlay.OverlayListPopup
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
@@ -44,7 +44,7 @@ fun OverlaySpinnerPreference(
|
|||||||
titleColor: BasicComponentColors = BasicComponentDefaults.titleColor(),
|
titleColor: BasicComponentColors = BasicComponentDefaults.titleColor(),
|
||||||
summary: String? = null,
|
summary: String? = null,
|
||||||
summaryColor: BasicComponentColors = BasicComponentDefaults.summaryColor(),
|
summaryColor: BasicComponentColors = BasicComponentDefaults.summaryColor(),
|
||||||
spinnerColors: SpinnerColors = SpinnerDefaults.spinnerColors(),
|
spinnerColors: DropdownColors = DropdownDefaults.dropdownColors(),
|
||||||
startAction: @Composable (() -> Unit)? = null,
|
startAction: @Composable (() -> Unit)? = null,
|
||||||
bottomAction: (@Composable () -> Unit)? = null,
|
bottomAction: (@Composable () -> Unit)? = null,
|
||||||
insideMargin: PaddingValues = BasicComponentDefaults.InsideMargin,
|
insideMargin: PaddingValues = BasicComponentDefaults.InsideMargin,
|
||||||
@@ -145,7 +145,7 @@ private fun OverlaySpinnerPopup(
|
|||||||
onDismissFinished: () -> Unit,
|
onDismissFinished: () -> Unit,
|
||||||
maxHeight: Dp?,
|
maxHeight: Dp?,
|
||||||
hapticFeedback: HapticFeedback,
|
hapticFeedback: HapticFeedback,
|
||||||
spinnerColors: SpinnerColors,
|
spinnerColors: DropdownColors,
|
||||||
renderInRootScaffold: Boolean,
|
renderInRootScaffold: Boolean,
|
||||||
onSelectedIndexChange: ((Int) -> Unit)?,
|
onSelectedIndexChange: ((Int) -> Unit)?,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.graphics.RectangleShape
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerColors
|
import top.yukonga.miuix.kmp.basic.DropdownColors
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ fun SpinnerItemImpl(
|
|||||||
entryCount: Int,
|
entryCount: Int,
|
||||||
isSelected: Boolean,
|
isSelected: Boolean,
|
||||||
index: Int,
|
index: Int,
|
||||||
spinnerColors: SpinnerColors,
|
spinnerColors: DropdownColors,
|
||||||
dialogMode: Boolean = false,
|
dialogMode: Boolean = false,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
onSelectedIndexChange: (Int) -> Unit,
|
onSelectedIndexChange: (Int) -> Unit,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.github.miuzarte.scrcpyforandroid.pages
|
package io.github.miuzarte.scrcpyforandroid.pages
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -15,6 +14,7 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -72,7 +72,6 @@ import top.yukonga.miuix.kmp.blur.layerBackdrop
|
|||||||
import top.yukonga.miuix.kmp.blur.rememberLayerBackdrop
|
import top.yukonga.miuix.kmp.blur.rememberLayerBackdrop
|
||||||
import top.yukonga.miuix.kmp.blur.textureBlur
|
import top.yukonga.miuix.kmp.blur.textureBlur
|
||||||
import top.yukonga.miuix.kmp.preference.ArrowPreference
|
import top.yukonga.miuix.kmp.preference.ArrowPreference
|
||||||
import top.yukonga.miuix.kmp.shapes.SmoothRoundedCornerShape
|
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.textStyles
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.textStyles
|
||||||
import java.util.Locale.getDefault
|
import java.util.Locale.getDefault
|
||||||
@@ -208,7 +207,7 @@ private fun AboutContent(
|
|||||||
Card(
|
Card(
|
||||||
modifier = modifier.textureBlur(
|
modifier = modifier.textureBlur(
|
||||||
backdrop = backdrop,
|
backdrop = backdrop,
|
||||||
shape = SmoothRoundedCornerShape(16.dp),
|
shape = RoundedCornerShape(16.dp),
|
||||||
blurRadius = 60f,
|
blurRadius = 60f,
|
||||||
noiseCoefficient = BlurDefaults.NoiseCoefficient,
|
noiseCoefficient = BlurDefaults.NoiseCoefficient,
|
||||||
colors = BlurColors(blendColors = cardBlendColors),
|
colors = BlurColors(blendColors = cardBlendColors),
|
||||||
@@ -285,7 +284,7 @@ private fun AboutContent(
|
|||||||
}
|
}
|
||||||
.textureBlur(
|
.textureBlur(
|
||||||
backdrop = backdrop,
|
backdrop = backdrop,
|
||||||
shape = SmoothRoundedCornerShape(16.dp),
|
shape = RoundedCornerShape(16.dp),
|
||||||
blurRadius = 150f,
|
blurRadius = 150f,
|
||||||
noiseCoefficient = BlurDefaults.NoiseCoefficient,
|
noiseCoefficient = BlurDefaults.NoiseCoefficient,
|
||||||
colors = BlurColors(blendColors = heroBlendColors),
|
colors = BlurColors(blendColors = heroBlendColors),
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ import io.github.miuzarte.scrcpyforandroid.services.ConnectionStateStore
|
|||||||
import io.github.miuzarte.scrcpyforandroid.services.DeviceAdbAutoReconnectManager
|
import io.github.miuzarte.scrcpyforandroid.services.DeviceAdbAutoReconnectManager
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.DeviceAdbConnectionCoordinator
|
import io.github.miuzarte.scrcpyforandroid.services.DeviceAdbConnectionCoordinator
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.EventLogger
|
import io.github.miuzarte.scrcpyforandroid.services.EventLogger
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.LocalSnackbarController
|
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
|
import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
|
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
|
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
|
||||||
@@ -77,12 +76,10 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import top.yukonga.miuix.kmp.basic.Card
|
import top.yukonga.miuix.kmp.basic.Card
|
||||||
import top.yukonga.miuix.kmp.basic.DropdownImpl
|
import top.yukonga.miuix.kmp.basic.DropdownEntry
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownItem
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.IconButton
|
import top.yukonga.miuix.kmp.basic.IconButton
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
|
||||||
import top.yukonga.miuix.kmp.basic.Scaffold
|
import top.yukonga.miuix.kmp.basic.Scaffold
|
||||||
import top.yukonga.miuix.kmp.basic.ScrollBehavior
|
import top.yukonga.miuix.kmp.basic.ScrollBehavior
|
||||||
import top.yukonga.miuix.kmp.basic.SmallTopAppBar
|
import top.yukonga.miuix.kmp.basic.SmallTopAppBar
|
||||||
@@ -91,7 +88,7 @@ import top.yukonga.miuix.kmp.basic.TopAppBar
|
|||||||
import top.yukonga.miuix.kmp.blur.layerBackdrop
|
import top.yukonga.miuix.kmp.blur.layerBackdrop
|
||||||
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
||||||
import top.yukonga.miuix.kmp.icon.extended.More
|
import top.yukonga.miuix.kmp.icon.extended.More
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayListPopup
|
import top.yukonga.miuix.kmp.menu.OverlayIconDropdownMenu
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
|
|
||||||
private const val PREVIEW_CARD_ITEM_KEY = "preview_card"
|
private const val PREVIEW_CARD_ITEM_KEY = "preview_card"
|
||||||
@@ -117,7 +114,6 @@ internal fun DeviceTabScreen(
|
|||||||
val viewModel: DeviceTabViewModel = viewModel(factory = viewModelFactory)
|
val viewModel: DeviceTabViewModel = viewModel(factory = viewModelFactory)
|
||||||
|
|
||||||
val navigator = LocalRootNavigator.current
|
val navigator = LocalRootNavigator.current
|
||||||
var showThreePointMenu by rememberSaveable { mutableStateOf(false) }
|
|
||||||
var useCompactTopAppBar by remember { mutableStateOf(false) }
|
var useCompactTopAppBar by remember { mutableStateOf(false) }
|
||||||
var showTwoPaneSideAction by remember { mutableStateOf(false) }
|
var showTwoPaneSideAction by remember { mutableStateOf(false) }
|
||||||
var configPanelOnLeft by remember { mutableStateOf(true) }
|
var configPanelOnLeft by remember { mutableStateOf(true) }
|
||||||
@@ -145,56 +141,35 @@ internal fun DeviceTabScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Box {
|
OverlayIconDropdownMenu(
|
||||||
IconButton(
|
entry = DropdownEntry(
|
||||||
onClick = { showThreePointMenu = true },
|
items = listOf(
|
||||||
holdDownState = showThreePointMenu,
|
DropdownItem(
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = MiuixIcons.More,
|
|
||||||
contentDescription = stringResource(R.string.cd_more),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OverlayListPopup(
|
|
||||||
show = showThreePointMenu,
|
|
||||||
popupPositionProvider = ListPopupDefaults.ContextMenuPositionProvider,
|
|
||||||
alignment = PopupPositionProvider.Align.TopEnd,
|
|
||||||
onDismissRequest = { showThreePointMenu = false },
|
|
||||||
) {
|
|
||||||
ListPopupColumn {
|
|
||||||
DropdownImpl(
|
|
||||||
text = stringResource(R.string.device_menu_quick_sort),
|
text = stringResource(R.string.device_menu_quick_sort),
|
||||||
optionSize = 3,
|
onClick = {
|
||||||
isSelected = false,
|
|
||||||
index = 0,
|
|
||||||
onSelectedIndexChange = {
|
|
||||||
onOpenReorderDevices()
|
onOpenReorderDevices()
|
||||||
showThreePointMenu = false
|
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
DropdownImpl(
|
DropdownItem(
|
||||||
text = stringResource(R.string.device_menu_virtual_button_sort),
|
text = stringResource(R.string.device_menu_virtual_button_sort),
|
||||||
optionSize = 3,
|
onClick = {
|
||||||
isSelected = false,
|
|
||||||
index = 1,
|
|
||||||
onSelectedIndexChange = {
|
|
||||||
navigator.push(RootScreen.VirtualButtonOrder)
|
navigator.push(RootScreen.VirtualButtonOrder)
|
||||||
showThreePointMenu = false
|
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
DropdownImpl(
|
DropdownItem(
|
||||||
text = stringResource(R.string.device_menu_clear_logs),
|
text = stringResource(R.string.device_menu_clear_logs),
|
||||||
optionSize = 3,
|
|
||||||
isSelected = false,
|
|
||||||
index = 2,
|
|
||||||
enabled = EventLogger.hasLogs(),
|
enabled = EventLogger.hasLogs(),
|
||||||
onSelectedIndexChange = {
|
onClick = {
|
||||||
EventLogger.clearLogs()
|
EventLogger.clearLogs()
|
||||||
showThreePointMenu = false
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = MiuixIcons.More,
|
||||||
|
contentDescription = stringResource(R.string.cd_more),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (useCompactTopAppBar) SmallTopAppBar(
|
if (useCompactTopAppBar) SmallTopAppBar(
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ import io.github.miuzarte.scrcpyforandroid.scaffolds.LazyColumn
|
|||||||
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.DirectoryDownloadSnapshot
|
import io.github.miuzarte.scrcpyforandroid.services.DirectoryDownloadSnapshot
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.FileManagerService
|
import io.github.miuzarte.scrcpyforandroid.services.FileManagerService
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.LocalSnackbarController
|
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.RemoteFileEntry
|
import io.github.miuzarte.scrcpyforandroid.services.RemoteFileEntry
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.RemoteFileKind
|
import io.github.miuzarte.scrcpyforandroid.services.RemoteFileKind
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.RemoteFileStat
|
import io.github.miuzarte.scrcpyforandroid.services.RemoteFileStat
|
||||||
@@ -61,12 +60,10 @@ import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
|
|||||||
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
|
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
|
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
|
||||||
import top.yukonga.miuix.kmp.basic.Card
|
import top.yukonga.miuix.kmp.basic.Card
|
||||||
import top.yukonga.miuix.kmp.basic.DropdownImpl
|
import top.yukonga.miuix.kmp.basic.DropdownEntry
|
||||||
import top.yukonga.miuix.kmp.basic.HorizontalDivider
|
import top.yukonga.miuix.kmp.basic.DropdownItem
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.IconButton
|
import top.yukonga.miuix.kmp.basic.IconButton
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.PullToRefresh
|
import top.yukonga.miuix.kmp.basic.PullToRefresh
|
||||||
import top.yukonga.miuix.kmp.basic.PullToRefreshState
|
import top.yukonga.miuix.kmp.basic.PullToRefreshState
|
||||||
import top.yukonga.miuix.kmp.basic.Scaffold
|
import top.yukonga.miuix.kmp.basic.Scaffold
|
||||||
@@ -79,9 +76,9 @@ import top.yukonga.miuix.kmp.blur.layerBackdrop
|
|||||||
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
||||||
import top.yukonga.miuix.kmp.icon.extended.More
|
import top.yukonga.miuix.kmp.icon.extended.More
|
||||||
import top.yukonga.miuix.kmp.icon.extended.Tune
|
import top.yukonga.miuix.kmp.icon.extended.Tune
|
||||||
|
import top.yukonga.miuix.kmp.menu.OverlayIconDropdownMenu
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayDialog
|
import top.yukonga.miuix.kmp.overlay.OverlayDialog
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayListPopup
|
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
|
|
||||||
private const val INITIAL_REMOTE_PATH = "/storage/emulated/0"
|
private const val INITIAL_REMOTE_PATH = "/storage/emulated/0"
|
||||||
@@ -216,43 +213,33 @@ fun FileManagerScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
Box {
|
val sortOptions = listOf(
|
||||||
IconButton(
|
stringResource(R.string.fm_sort_name),
|
||||||
onClick = { showSortMenu = true },
|
stringResource(R.string.fm_sort_size),
|
||||||
holdDownState = showSortMenu
|
stringResource(R.string.fm_sort_time),
|
||||||
) {
|
stringResource(R.string.fm_sort_extension),
|
||||||
Icon(
|
)
|
||||||
imageVector = MiuixIcons.Tune,
|
val sortFieldIdx = when (sortField) {
|
||||||
contentDescription = stringResource(R.string.fm_cd_sort),
|
FileManagerSortField.NAME -> 0
|
||||||
)
|
FileManagerSortField.SIZE -> 1
|
||||||
}
|
FileManagerSortField.TIME -> 2
|
||||||
OverlayListPopup(
|
FileManagerSortField.EXTENSION -> 3
|
||||||
show = showSortMenu,
|
}
|
||||||
popupPositionProvider = ListPopupDefaults.ContextMenuPositionProvider,
|
val dirOptions = listOf(
|
||||||
onDismissRequest = { showSortMenu = false },
|
stringResource(R.string.fm_sort_asc),
|
||||||
) {
|
stringResource(R.string.fm_sort_desc),
|
||||||
ListPopupColumn {
|
)
|
||||||
val sortOptions = listOf(
|
val dirIdx = if (sortDescending) 1 else 0
|
||||||
stringResource(R.string.fm_sort_name),
|
OverlayIconDropdownMenu(
|
||||||
stringResource(R.string.fm_sort_size),
|
entries = listOf(
|
||||||
stringResource(R.string.fm_sort_time),
|
DropdownEntry(
|
||||||
stringResource(R.string.fm_sort_extension),
|
items = sortOptions.mapIndexed { i, option ->
|
||||||
)
|
DropdownItem(
|
||||||
val sortFieldIdx = when (sortField) {
|
|
||||||
FileManagerSortField.NAME -> 0
|
|
||||||
FileManagerSortField.SIZE -> 1
|
|
||||||
FileManagerSortField.TIME -> 2
|
|
||||||
FileManagerSortField.EXTENSION -> 3
|
|
||||||
}
|
|
||||||
sortOptions.forEachIndexed { i, option ->
|
|
||||||
DropdownImpl(
|
|
||||||
text = option,
|
text = option,
|
||||||
optionSize = sortOptions.size,
|
selected = i == sortFieldIdx,
|
||||||
isSelected = i == sortFieldIdx,
|
onClick = {
|
||||||
index = i,
|
|
||||||
onSelectedIndexChange = { index ->
|
|
||||||
viewModel.updateSort(
|
viewModel.updateSort(
|
||||||
sortBy = when (index) {
|
sortBy = when (i) {
|
||||||
1 -> FileManagerSortField.SIZE
|
1 -> FileManagerSortField.SIZE
|
||||||
2 -> FileManagerSortField.TIME
|
2 -> FileManagerSortField.TIME
|
||||||
3 -> FileManagerSortField.EXTENSION
|
3 -> FileManagerSortField.EXTENSION
|
||||||
@@ -262,67 +249,51 @@ fun FileManagerScreen(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
HorizontalDivider(modifier = Modifier.padding(horizontal = 20.dp))
|
),
|
||||||
val dirOptions = listOf(
|
DropdownEntry(
|
||||||
stringResource(R.string.fm_sort_asc),
|
items = dirOptions.mapIndexed { i, option ->
|
||||||
stringResource(R.string.fm_sort_desc),
|
DropdownItem(
|
||||||
)
|
|
||||||
val dirIdx = if (sortDescending) 1 else 0
|
|
||||||
dirOptions.forEachIndexed { i, option ->
|
|
||||||
DropdownImpl(
|
|
||||||
text = option,
|
text = option,
|
||||||
optionSize = dirOptions.size,
|
selected = i == dirIdx,
|
||||||
isSelected = i == dirIdx,
|
onClick = {
|
||||||
index = i,
|
|
||||||
onSelectedIndexChange = { index ->
|
|
||||||
viewModel.updateSort(
|
viewModel.updateSort(
|
||||||
descending = index == 1
|
descending = i == 1
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
),
|
||||||
}
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = MiuixIcons.Tune,
|
||||||
|
contentDescription = stringResource(R.string.fm_cd_sort),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Box {
|
|
||||||
IconButton(
|
OverlayIconDropdownMenu(
|
||||||
onClick = { showMenu = true },
|
entry = DropdownEntry(
|
||||||
holdDownState = showMenu,
|
items = listOf(
|
||||||
) {
|
DropdownItem(
|
||||||
Icon(
|
|
||||||
imageVector = MiuixIcons.More,
|
|
||||||
contentDescription = stringResource(R.string.cd_more),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OverlayListPopup(
|
|
||||||
show = showMenu,
|
|
||||||
popupPositionProvider = ListPopupDefaults.ContextMenuPositionProvider,
|
|
||||||
onDismissRequest = { showMenu = false },
|
|
||||||
) {
|
|
||||||
ListPopupColumn {
|
|
||||||
DropdownImpl(
|
|
||||||
text = stringResource(R.string.fm_menu_create_folder),
|
text = stringResource(R.string.fm_menu_create_folder),
|
||||||
optionSize = 2,
|
onClick = {
|
||||||
isSelected = false,
|
|
||||||
index = 0,
|
|
||||||
onSelectedIndexChange = {
|
|
||||||
showMenu = false
|
|
||||||
newFolderName = ""
|
newFolderName = ""
|
||||||
showCreateFolderDialog = true
|
showCreateFolderDialog = true
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
DropdownImpl(
|
DropdownItem(
|
||||||
text = stringResource(R.string.fm_menu_upload),
|
text = stringResource(R.string.fm_menu_upload),
|
||||||
optionSize = 2,
|
onClick = {
|
||||||
isSelected = false,
|
|
||||||
index = 1,
|
|
||||||
onSelectedIndexChange = {
|
|
||||||
showMenu = false
|
|
||||||
uploadLauncher.launch(arrayOf("*/*"))
|
uploadLauncher.launch(arrayOf("*/*"))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = MiuixIcons.More,
|
||||||
|
contentDescription = stringResource(R.string.cd_more),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -725,7 +725,6 @@ fun MainScreen() {
|
|||||||
|
|
||||||
MiuixTheme(
|
MiuixTheme(
|
||||||
controller = themeController,
|
controller = themeController,
|
||||||
smoothRounding = asBundle.smoothCorner,
|
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalEnableBlur provides asBundle.blur,
|
LocalEnableBlur provides asBundle.blur,
|
||||||
|
|||||||
@@ -84,12 +84,10 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.Card
|
import top.yukonga.miuix.kmp.basic.Card
|
||||||
import top.yukonga.miuix.kmp.basic.DropdownImpl
|
import top.yukonga.miuix.kmp.basic.DropdownEntry
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownItem
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.IconButton
|
import top.yukonga.miuix.kmp.basic.IconButton
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
|
||||||
import top.yukonga.miuix.kmp.basic.Scaffold
|
import top.yukonga.miuix.kmp.basic.Scaffold
|
||||||
import top.yukonga.miuix.kmp.basic.ScrollBehavior
|
import top.yukonga.miuix.kmp.basic.ScrollBehavior
|
||||||
import top.yukonga.miuix.kmp.basic.SnackbarHost
|
import top.yukonga.miuix.kmp.basic.SnackbarHost
|
||||||
@@ -102,9 +100,9 @@ import top.yukonga.miuix.kmp.blur.layerBackdrop
|
|||||||
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
||||||
import top.yukonga.miuix.kmp.icon.extended.More
|
import top.yukonga.miuix.kmp.icon.extended.More
|
||||||
import top.yukonga.miuix.kmp.icon.extended.Store
|
import top.yukonga.miuix.kmp.icon.extended.Store
|
||||||
|
import top.yukonga.miuix.kmp.menu.OverlayIconDropdownMenu
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayDialog
|
import top.yukonga.miuix.kmp.overlay.OverlayDialog
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayListPopup
|
|
||||||
import top.yukonga.miuix.kmp.preference.OverlayDropdownPreference
|
import top.yukonga.miuix.kmp.preference.OverlayDropdownPreference
|
||||||
import top.yukonga.miuix.kmp.preference.SwitchPreference
|
import top.yukonga.miuix.kmp.preference.SwitchPreference
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
@@ -230,35 +228,23 @@ internal fun ScrcpyAllOptionsScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
Box {
|
OverlayIconDropdownMenu(
|
||||||
IconButton(
|
entry = DropdownEntry(
|
||||||
onClick = { showProfileMenu = true },
|
items = listOf(
|
||||||
holdDownState = showProfileMenu,
|
DropdownItem(
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = MiuixIcons.More,
|
|
||||||
contentDescription = stringResource(R.string.scrcpyopt_cd_profile_manage),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OverlayListPopup(
|
|
||||||
show = showProfileMenu,
|
|
||||||
popupPositionProvider = ListPopupDefaults.ContextMenuPositionProvider,
|
|
||||||
alignment = PopupPositionProvider.Align.TopEnd,
|
|
||||||
onDismissRequest = { showProfileMenu = false },
|
|
||||||
) {
|
|
||||||
ListPopupColumn {
|
|
||||||
DropdownImpl(
|
|
||||||
text = stringResource(R.string.scrcpyopt_manage_profiles),
|
text = stringResource(R.string.scrcpyopt_manage_profiles),
|
||||||
optionSize = 1,
|
onClick = {
|
||||||
isSelected = false,
|
|
||||||
index = 0,
|
|
||||||
onSelectedIndexChange = {
|
|
||||||
showManageProfilesSheet = true
|
showManageProfilesSheet = true
|
||||||
showProfileMenu = false
|
showProfileMenu = false
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = MiuixIcons.More,
|
||||||
|
contentDescription = stringResource(R.string.scrcpyopt_cd_profile_manage),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package io.github.miuzarte.scrcpyforandroid.pages
|
package io.github.miuzarte.scrcpyforandroid.pages
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
|
import androidx.activity.compose.LocalActivity
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
@@ -41,6 +41,7 @@ import androidx.compose.ui.unit.Dp
|
|||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import io.github.miuzarte.scrcpyforandroid.BuildConfig
|
import io.github.miuzarte.scrcpyforandroid.BuildConfig
|
||||||
import io.github.miuzarte.scrcpyforandroid.LockscreenPasswordActivity
|
import io.github.miuzarte.scrcpyforandroid.LockscreenPasswordActivity
|
||||||
|
import io.github.miuzarte.scrcpyforandroid.MainActivity
|
||||||
import io.github.miuzarte.scrcpyforandroid.R
|
import io.github.miuzarte.scrcpyforandroid.R
|
||||||
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
||||||
import io.github.miuzarte.scrcpyforandroid.nativecore.DirectAdbTransport
|
import io.github.miuzarte.scrcpyforandroid.nativecore.DirectAdbTransport
|
||||||
@@ -87,6 +88,11 @@ import java.io.File
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import android.provider.Settings as AndroidSettings
|
import android.provider.Settings as AndroidSettings
|
||||||
|
|
||||||
|
private val languages = listOf(
|
||||||
|
R.string.language_follow_system to "",
|
||||||
|
R.string.language_english to "en",
|
||||||
|
R.string.language_chinese to "zh",
|
||||||
|
)
|
||||||
private const val TERMINAL_FONT_RELATIVE_PATH = "terminal/font.ttf"
|
private const val TERMINAL_FONT_RELATIVE_PATH = "terminal/font.ttf"
|
||||||
private val monetPaletteStyleOptions = ThemePaletteStyle.entries.map { it.name }
|
private val monetPaletteStyleOptions = ThemePaletteStyle.entries.map { it.name }
|
||||||
private val monetColorSpecOptions = ThemeColorSpec.entries.map { it.name }
|
private val monetColorSpecOptions = ThemeColorSpec.entries.map { it.name }
|
||||||
@@ -159,6 +165,7 @@ fun SettingsPage(
|
|||||||
bottomInnerPadding: Dp,
|
bottomInnerPadding: Dp,
|
||||||
onOpenReorderDevices: () -> Unit,
|
onOpenReorderDevices: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val activity = LocalActivity.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val updateState by AppUpdateChecker.state.collectAsState()
|
val updateState by AppUpdateChecker.state.collectAsState()
|
||||||
|
|
||||||
@@ -292,6 +299,27 @@ fun SettingsPage(
|
|||||||
item {
|
item {
|
||||||
SectionSmallTitle(stringResource(R.string.section_theme))
|
SectionSmallTitle(stringResource(R.string.section_theme))
|
||||||
Card {
|
Card {
|
||||||
|
OverlayDropdownPreference(
|
||||||
|
title = stringResource(R.string.pref_title_language),
|
||||||
|
summary = stringResource(R.string.pref_summary_language),
|
||||||
|
entries = listOf(
|
||||||
|
DropdownEntry(
|
||||||
|
items = languages.map { lang ->
|
||||||
|
DropdownItem(
|
||||||
|
text = stringResource(lang.first),
|
||||||
|
selected = lang.second == asBundle.languageTag,
|
||||||
|
onClick = {
|
||||||
|
asBundle = asBundle.copy(
|
||||||
|
languageTag = lang.second
|
||||||
|
)
|
||||||
|
MainActivity.setAppLanguageTag(context, lang.second)
|
||||||
|
activity?.recreate()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
OverlayDropdownPreference(
|
OverlayDropdownPreference(
|
||||||
title = stringResource(R.string.pref_title_appearance_mode),
|
title = stringResource(R.string.pref_title_appearance_mode),
|
||||||
summary = stringResource(R.string.pref_summary_appearance_mode),
|
summary = stringResource(R.string.pref_summary_appearance_mode),
|
||||||
@@ -393,16 +421,6 @@ fun SettingsPage(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SwitchPreference(
|
|
||||||
title = stringResource(R.string.pref_title_smooth_corners),
|
|
||||||
summary = stringResource(R.string.pref_summary_smooth_corners),
|
|
||||||
checked = asBundle.smoothCorner,
|
|
||||||
onCheckedChange = {
|
|
||||||
asBundle = asBundle.copy(
|
|
||||||
smoothCorner = it
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,33 +553,41 @@ fun SettingsPage(
|
|||||||
entries = listOf(
|
entries = listOf(
|
||||||
DropdownEntry(
|
DropdownEntry(
|
||||||
items = FullscreenVirtualButtonDock
|
items = FullscreenVirtualButtonDock
|
||||||
.modeItemsResIds.map { DropdownItem(stringResource(it)) },
|
.modeItemsResIds.mapIndexed { index, id ->
|
||||||
selectedIndex = fullscreenVirtualButtonDock.modeIndex,
|
DropdownItem(
|
||||||
onSelectedIndexChange = { modeIndex ->
|
text = stringResource(id),
|
||||||
asBundle = asBundle.copy(
|
selected = index == fullscreenVirtualButtonDock.modeIndex,
|
||||||
fullscreenVirtualButtonDock = FullscreenVirtualButtonDock
|
onClick = {
|
||||||
.fromModeAndDirection(
|
asBundle = asBundle.copy(
|
||||||
modeIndex = modeIndex,
|
fullscreenVirtualButtonDock = FullscreenVirtualButtonDock
|
||||||
directionIndex = fullscreenVirtualButtonDock.directionIndex,
|
.fromModeAndDirection(
|
||||||
)
|
modeIndex = index,
|
||||||
.toStoredValue()
|
directionIndex = fullscreenVirtualButtonDock.directionIndex,
|
||||||
)
|
)
|
||||||
},
|
.toStoredValue()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
),
|
),
|
||||||
DropdownEntry(
|
DropdownEntry(
|
||||||
items = FullscreenVirtualButtonDock
|
items = FullscreenVirtualButtonDock
|
||||||
.directionItemsResIds.map { DropdownItem(stringResource(it)) },
|
.directionItemsResIds.mapIndexed { index, id ->
|
||||||
selectedIndex = fullscreenVirtualButtonDock.directionIndex,
|
DropdownItem(
|
||||||
onSelectedIndexChange = { directionIndex ->
|
text = stringResource(id),
|
||||||
asBundle = asBundle.copy(
|
selected = index == fullscreenVirtualButtonDock.directionIndex,
|
||||||
fullscreenVirtualButtonDock = FullscreenVirtualButtonDock
|
onClick = {
|
||||||
.fromModeAndDirection(
|
asBundle = asBundle.copy(
|
||||||
modeIndex = fullscreenVirtualButtonDock.modeIndex,
|
fullscreenVirtualButtonDock = FullscreenVirtualButtonDock
|
||||||
directionIndex = directionIndex,
|
.fromModeAndDirection(
|
||||||
)
|
modeIndex = fullscreenVirtualButtonDock.modeIndex,
|
||||||
.toStoredValue()
|
directionIndex = index,
|
||||||
)
|
)
|
||||||
},
|
.toStoredValue()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title = stringResource(R.string.pref_title_virtual_button_direction),
|
title = stringResource(R.string.pref_title_virtual_button_direction),
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ fun StreamScreen(activity: StreamActivity) {
|
|||||||
|
|
||||||
MiuixTheme(
|
MiuixTheme(
|
||||||
controller = themeController,
|
controller = themeController,
|
||||||
smoothRounding = asBundle.smoothCorner,
|
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalSnackbarController provides snackbarController,
|
LocalSnackbarController provides snackbarController,
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ import androidx.compose.ui.graphics.luminance
|
|||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -52,16 +52,14 @@ import io.github.miuzarte.scrcpyforandroid.R
|
|||||||
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.LocalInputService
|
import io.github.miuzarte.scrcpyforandroid.services.LocalInputService
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.LocalSnackbarController
|
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
|
import io.github.miuzarte.scrcpyforandroid.ui.BlurredBar
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
|
import io.github.miuzarte.scrcpyforandroid.ui.LocalEnableBlur
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
|
import io.github.miuzarte.scrcpyforandroid.ui.contextClick
|
||||||
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
|
import io.github.miuzarte.scrcpyforandroid.ui.rememberBlurBackdrop
|
||||||
import top.yukonga.miuix.kmp.basic.DropdownImpl
|
import top.yukonga.miuix.kmp.basic.DropdownEntry
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownItem
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.IconButton
|
import top.yukonga.miuix.kmp.basic.IconButton
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.Scaffold
|
import top.yukonga.miuix.kmp.basic.Scaffold
|
||||||
import top.yukonga.miuix.kmp.basic.SmallTopAppBar
|
import top.yukonga.miuix.kmp.basic.SmallTopAppBar
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
@@ -69,8 +67,8 @@ import top.yukonga.miuix.kmp.basic.TextField
|
|||||||
import top.yukonga.miuix.kmp.blur.layerBackdrop
|
import top.yukonga.miuix.kmp.blur.layerBackdrop
|
||||||
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
||||||
import top.yukonga.miuix.kmp.icon.extended.More
|
import top.yukonga.miuix.kmp.icon.extended.More
|
||||||
|
import top.yukonga.miuix.kmp.menu.OverlayIconDropdownMenu
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet
|
||||||
import top.yukonga.miuix.kmp.overlay.OverlayListPopup
|
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@@ -98,7 +96,6 @@ fun TerminalScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val blurBackdrop = rememberBlurBackdrop(LocalEnableBlur.current)
|
val blurBackdrop = rememberBlurBackdrop(LocalEnableBlur.current)
|
||||||
val blurActive = blurBackdrop != null
|
val blurActive = blurBackdrop != null
|
||||||
var showMenu by rememberSaveable { mutableStateOf(false) }
|
|
||||||
var showOutputSheet by rememberSaveable { mutableStateOf(false) }
|
var showOutputSheet by rememberSaveable { mutableStateOf(false) }
|
||||||
var output by rememberSaveable { mutableStateOf("") }
|
var output by rememberSaveable { mutableStateOf("") }
|
||||||
|
|
||||||
@@ -111,45 +108,29 @@ fun TerminalScreen(
|
|||||||
if (blurActive) Color.Transparent
|
if (blurActive) Color.Transparent
|
||||||
else colorScheme.surface,
|
else colorScheme.surface,
|
||||||
actions = {
|
actions = {
|
||||||
Box {
|
OverlayIconDropdownMenu(
|
||||||
IconButton(
|
entry = DropdownEntry(
|
||||||
onClick = { showMenu = true },
|
items = listOf(
|
||||||
holdDownState = showMenu,
|
DropdownItem(
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = MiuixIcons.More,
|
|
||||||
contentDescription = stringResource(R.string.cd_more),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OverlayListPopup(
|
|
||||||
show = showMenu,
|
|
||||||
popupPositionProvider = ListPopupDefaults.ContextMenuPositionProvider,
|
|
||||||
onDismissRequest = { showMenu = false },
|
|
||||||
) {
|
|
||||||
ListPopupColumn {
|
|
||||||
DropdownImpl(
|
|
||||||
text = stringResource(R.string.terminal_menu_free_copy),
|
text = stringResource(R.string.terminal_menu_free_copy),
|
||||||
optionSize = 2,
|
|
||||||
isSelected = false,
|
|
||||||
index = 0,
|
|
||||||
enabled = output.isNotBlank(),
|
enabled = output.isNotBlank(),
|
||||||
onSelectedIndexChange = {
|
onClick = {
|
||||||
showMenu = false
|
|
||||||
showOutputSheet = true
|
showOutputSheet = true
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
DropdownImpl(
|
DropdownItem(
|
||||||
text = stringResource(R.string.terminal_menu_clear_screen),
|
text = stringResource(R.string.terminal_menu_clear_screen),
|
||||||
optionSize = 2,
|
onClick = {
|
||||||
isSelected = false,
|
|
||||||
index = 1,
|
|
||||||
onSelectedIndexChange = {
|
|
||||||
showMenu = false
|
|
||||||
output = ""
|
output = ""
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = MiuixIcons.More,
|
||||||
|
contentDescription = stringResource(R.string.cd_more),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -175,7 +156,6 @@ fun TerminalScreen(
|
|||||||
output = output,
|
output = output,
|
||||||
onDismissRequest = { showOutputSheet = false },
|
onDismissRequest = { showOutputSheet = false },
|
||||||
onCopyAll = {
|
onCopyAll = {
|
||||||
showMenu = false
|
|
||||||
LocalInputService.setClipboardText(context, output)
|
LocalInputService.setClipboardText(context, output)
|
||||||
AppRuntime.snackbar(R.string.terminal_copied_all)
|
AppRuntime.snackbar(R.string.terminal_copied_all)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.github.miuzarte.scrcpyforandroid.password
|
package io.github.miuzarte.scrcpyforandroid.password
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.activity.compose.LocalActivity
|
import androidx.activity.compose.LocalActivity
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -13,23 +12,18 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import io.github.miuzarte.scrcpyforandroid.R
|
import io.github.miuzarte.scrcpyforandroid.R
|
||||||
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
import io.github.miuzarte.scrcpyforandroid.services.AppRuntime
|
||||||
import io.github.miuzarte.scrcpyforandroid.services.LocalSnackbarController
|
|
||||||
import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings
|
import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownDefaults
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownItem
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerEntry
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerItemImpl
|
import top.yukonga.miuix.kmp.basic.SpinnerItemImpl
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
||||||
@@ -37,7 +31,6 @@ import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme
|
|||||||
@Composable
|
@Composable
|
||||||
fun PasswordPickerPopupContent(onDismissRequest: () -> Unit) {
|
fun PasswordPickerPopupContent(onDismissRequest: () -> Unit) {
|
||||||
val fragActivity = LocalActivity.current as? FragmentActivity
|
val fragActivity = LocalActivity.current as? FragmentActivity
|
||||||
val taskScope = remember { CoroutineScope(SupervisorJob() + Dispatchers.IO) }
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val passwordUseCase = remember { PasswordUseCase() }
|
val passwordUseCase = remember { PasswordUseCase() }
|
||||||
val entries by PasswordRepository.entriesState.collectAsState()
|
val entries by PasswordRepository.entriesState.collectAsState()
|
||||||
@@ -49,7 +42,7 @@ fun PasswordPickerPopupContent(onDismissRequest: () -> Unit) {
|
|||||||
val textBurned = stringResource(R.string.password_status_burned)
|
val textBurned = stringResource(R.string.password_status_burned)
|
||||||
val spinnerEntries = remember(entries) {
|
val spinnerEntries = remember(entries) {
|
||||||
entries.map { entry ->
|
entries.map { entry ->
|
||||||
SpinnerEntry(
|
DropdownItem(
|
||||||
icon = {
|
icon = {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector =
|
imageVector =
|
||||||
@@ -123,7 +116,7 @@ fun PasswordPickerPopupContent(onDismissRequest: () -> Unit) {
|
|||||||
entryCount = spinnerEntries.size,
|
entryCount = spinnerEntries.size,
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
index = index,
|
index = index,
|
||||||
spinnerColors = SpinnerDefaults.spinnerColors(),
|
spinnerColors = DropdownDefaults.dropdownColors(),
|
||||||
dialogMode = false,
|
dialogMode = false,
|
||||||
onSelectedIndexChange = ::fillPassword,
|
onSelectedIndexChange = ::fillPassword,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
package io.github.miuzarte.scrcpyforandroid.scaffolds
|
package io.github.miuzarte.scrcpyforandroid.scaffolds
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import io.github.miuzarte.scrcpyforandroid.R
|
import io.github.miuzarte.scrcpyforandroid.R
|
||||||
import io.github.miuzarte.scrcpyforandroid.miuix.OverlaySpinnerPreference
|
import io.github.miuzarte.scrcpyforandroid.miuix.OverlaySpinnerPreference
|
||||||
import io.github.miuzarte.scrcpyforandroid.miuix.SpinnerEntry
|
import io.github.miuzarte.scrcpyforandroid.miuix.SpinnerEntry
|
||||||
import top.yukonga.miuix.kmp.basic.BasicComponentColors
|
import top.yukonga.miuix.kmp.basic.BasicComponentColors
|
||||||
import top.yukonga.miuix.kmp.basic.BasicComponentDefaults
|
import top.yukonga.miuix.kmp.basic.BasicComponentDefaults
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownColors
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.InfiniteProgressIndicator
|
import top.yukonga.miuix.kmp.basic.InfiniteProgressIndicator
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerColors
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerDefaults
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [OverlaySpinnerPreference] wrapper with fallback value display and loading state.
|
* [OverlaySpinnerPreference] wrapper with fallback value display and loading state.
|
||||||
@@ -34,7 +32,7 @@ fun OverlaySpinnerWithFallback(
|
|||||||
titleColor: BasicComponentColors = BasicComponentDefaults.titleColor(),
|
titleColor: BasicComponentColors = BasicComponentDefaults.titleColor(),
|
||||||
summary: String? = null,
|
summary: String? = null,
|
||||||
summaryColor: BasicComponentColors = BasicComponentDefaults.summaryColor(),
|
summaryColor: BasicComponentColors = BasicComponentDefaults.summaryColor(),
|
||||||
spinnerColors: SpinnerColors = SpinnerDefaults.spinnerColors(),
|
spinnerColors: DropdownColors = DropdownDefaults.dropdownColors(),
|
||||||
startAction: @Composable (() -> Unit)? = null,
|
startAction: @Composable (() -> Unit)? = null,
|
||||||
bottomAction: (@Composable () -> Unit)? = null,
|
bottomAction: (@Composable () -> Unit)? = null,
|
||||||
insideMargin: PaddingValues = BasicComponentDefaults.InsideMargin,
|
insideMargin: PaddingValues = BasicComponentDefaults.InsideMargin,
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val LANGUAGE_TAG = Pair(
|
||||||
|
stringPreferencesKey("language_tag"),
|
||||||
|
"",
|
||||||
|
)
|
||||||
// Theme
|
// Theme
|
||||||
val THEME_BASE_INDEX = Pair(
|
val THEME_BASE_INDEX = Pair(
|
||||||
intPreferencesKey("theme_base_index"),
|
intPreferencesKey("theme_base_index"),
|
||||||
@@ -121,10 +125,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
booleanPreferencesKey("floating_bottom_bar_blur"),
|
booleanPreferencesKey("floating_bottom_bar_blur"),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
val SMOOTH_CORNER = Pair(
|
|
||||||
booleanPreferencesKey("smooth_corner"),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Scrcpy
|
// Scrcpy
|
||||||
val LOW_LATENCY = Pair(
|
val LOW_LATENCY = Pair(
|
||||||
@@ -302,6 +302,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
@Parcelize
|
@Parcelize
|
||||||
data class Bundle(
|
data class Bundle(
|
||||||
// Theme
|
// Theme
|
||||||
|
val languageTag: String,
|
||||||
val themeBaseIndex: Int,
|
val themeBaseIndex: Int,
|
||||||
val monet: Boolean,
|
val monet: Boolean,
|
||||||
val monetSeedIndex: Int,
|
val monetSeedIndex: Int,
|
||||||
@@ -310,7 +311,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
val blur: Boolean,
|
val blur: Boolean,
|
||||||
val floatingBottomBar: Boolean,
|
val floatingBottomBar: Boolean,
|
||||||
val floatingBottomBarBlur: Boolean,
|
val floatingBottomBarBlur: Boolean,
|
||||||
val smoothCorner: Boolean,
|
|
||||||
|
|
||||||
// Scrcpy
|
// Scrcpy
|
||||||
val lowLatency: Boolean,
|
val lowLatency: Boolean,
|
||||||
@@ -365,6 +365,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
|
|
||||||
private val bundleFields = arrayOf<BundleField<Bundle>>(
|
private val bundleFields = arrayOf<BundleField<Bundle>>(
|
||||||
// Theme
|
// Theme
|
||||||
|
bundleField(LANGUAGE_TAG) { it.languageTag },
|
||||||
bundleField(THEME_BASE_INDEX) { it.themeBaseIndex },
|
bundleField(THEME_BASE_INDEX) { it.themeBaseIndex },
|
||||||
bundleField(MONET) { it.monet },
|
bundleField(MONET) { it.monet },
|
||||||
bundleField(MONET_SEED_INDEX) { it.monetSeedIndex },
|
bundleField(MONET_SEED_INDEX) { it.monetSeedIndex },
|
||||||
@@ -373,7 +374,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
bundleField(BLUR) { it.blur },
|
bundleField(BLUR) { it.blur },
|
||||||
bundleField(FLOATING_BOTTOM_BAR) { it.floatingBottomBar },
|
bundleField(FLOATING_BOTTOM_BAR) { it.floatingBottomBar },
|
||||||
bundleField(FLOATING_BOTTOM_BAR_BLUR) { it.floatingBottomBarBlur },
|
bundleField(FLOATING_BOTTOM_BAR_BLUR) { it.floatingBottomBarBlur },
|
||||||
bundleField(SMOOTH_CORNER) { it.smoothCorner },
|
|
||||||
|
|
||||||
// Scrcpy
|
// Scrcpy
|
||||||
bundleField(LOW_LATENCY) { it.lowLatency },
|
bundleField(LOW_LATENCY) { it.lowLatency },
|
||||||
@@ -429,6 +429,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
|
|
||||||
private fun bundleFromPreferences(preferences: Preferences) = Bundle(
|
private fun bundleFromPreferences(preferences: Preferences) = Bundle(
|
||||||
// Theme
|
// Theme
|
||||||
|
languageTag = preferences.read(LANGUAGE_TAG),
|
||||||
themeBaseIndex = preferences.read(THEME_BASE_INDEX),
|
themeBaseIndex = preferences.read(THEME_BASE_INDEX),
|
||||||
monet = preferences.read(MONET),
|
monet = preferences.read(MONET),
|
||||||
monetSeedIndex = preferences.read(MONET_SEED_INDEX),
|
monetSeedIndex = preferences.read(MONET_SEED_INDEX),
|
||||||
@@ -437,7 +438,6 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
|
|||||||
blur = preferences.read(BLUR),
|
blur = preferences.read(BLUR),
|
||||||
floatingBottomBar = preferences.read(FLOATING_BOTTOM_BAR),
|
floatingBottomBar = preferences.read(FLOATING_BOTTOM_BAR),
|
||||||
floatingBottomBarBlur = preferences.read(FLOATING_BOTTOM_BAR_BLUR),
|
floatingBottomBarBlur = preferences.read(FLOATING_BOTTOM_BAR_BLUR),
|
||||||
smoothCorner = preferences.read(SMOOTH_CORNER),
|
|
||||||
|
|
||||||
// Scrcpy
|
// Scrcpy
|
||||||
lowLatency = preferences.read(LOW_LATENCY),
|
lowLatency = preferences.read(LOW_LATENCY),
|
||||||
|
|||||||
@@ -17,15 +17,15 @@ import androidx.compose.material.icons.rounded.Refresh
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import io.github.miuzarte.scrcpyforandroid.R
|
import io.github.miuzarte.scrcpyforandroid.R
|
||||||
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownColors
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.IconButton
|
import top.yukonga.miuix.kmp.basic.IconButton
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerColors
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
||||||
import top.yukonga.miuix.kmp.icon.extended.Store
|
import top.yukonga.miuix.kmp.icon.extended.Store
|
||||||
@@ -51,7 +51,6 @@ fun AppListBottomSheet(
|
|||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
onRefresh: () -> Unit,
|
onRefresh: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val spinnerColors = SpinnerDefaults.spinnerColors()
|
|
||||||
OverlayBottomSheet(
|
OverlayBottomSheet(
|
||||||
show = show,
|
show = show,
|
||||||
title = title,
|
title = title,
|
||||||
@@ -98,7 +97,7 @@ fun AppListBottomSheet(
|
|||||||
items(items = entries, key = { it.key }) { entry ->
|
items(items = entries, key = { it.key }) { entry ->
|
||||||
AppListBottomSheetItem(
|
AppListBottomSheetItem(
|
||||||
entry = entry,
|
entry = entry,
|
||||||
spinnerColors = spinnerColors,
|
spinnerColors = DropdownDefaults.dropdownColors(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +109,7 @@ fun AppListBottomSheet(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun AppListBottomSheetItem(
|
private fun AppListBottomSheetItem(
|
||||||
entry: AppListEntry,
|
entry: AppListEntry,
|
||||||
spinnerColors: SpinnerColors,
|
spinnerColors: DropdownColors,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
|||||||
@@ -71,12 +71,12 @@ import kotlinx.coroutines.SupervisorJob
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import top.yukonga.miuix.kmp.basic.Button
|
import top.yukonga.miuix.kmp.basic.Button
|
||||||
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
import top.yukonga.miuix.kmp.basic.ButtonDefaults
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownDefaults
|
||||||
|
import top.yukonga.miuix.kmp.basic.DropdownItem
|
||||||
import top.yukonga.miuix.kmp.basic.Icon
|
import top.yukonga.miuix.kmp.basic.Icon
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
||||||
import top.yukonga.miuix.kmp.basic.ListPopupDefaults
|
import top.yukonga.miuix.kmp.basic.ListPopupDefaults
|
||||||
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerDefaults
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerEntry
|
|
||||||
import top.yukonga.miuix.kmp.basic.SpinnerItemImpl
|
import top.yukonga.miuix.kmp.basic.SpinnerItemImpl
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
import top.yukonga.miuix.kmp.basic.Text
|
||||||
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
import top.yukonga.miuix.kmp.icon.MiuixIcons
|
||||||
@@ -690,7 +690,7 @@ class VirtualButtonBar(
|
|||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
val spinnerItems = actions.map { action ->
|
val spinnerItems = actions.map { action ->
|
||||||
val title = stringResource(action.titleResId)
|
val title = stringResource(action.titleResId)
|
||||||
SpinnerEntry(
|
DropdownItem(
|
||||||
icon = {
|
icon = {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = action.icon,
|
imageVector = action.icon,
|
||||||
@@ -719,7 +719,7 @@ class VirtualButtonBar(
|
|||||||
entryCount = spinnerItems.size,
|
entryCount = spinnerItems.size,
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
index = index,
|
index = index,
|
||||||
spinnerColors = SpinnerDefaults.spinnerColors(),
|
spinnerColors = DropdownDefaults.dropdownColors(),
|
||||||
dialogMode = false,
|
dialogMode = false,
|
||||||
onSelectedIndexChange = { selectedIdx ->
|
onSelectedIndexChange = { selectedIdx ->
|
||||||
haptic.confirm()
|
haptic.confirm()
|
||||||
|
|||||||
@@ -246,6 +246,8 @@
|
|||||||
<string name="pref_summary_clear_logs_on_exit">双击返回退出应用时清除日志</string>
|
<string name="pref_summary_clear_logs_on_exit">双击返回退出应用时清除日志</string>
|
||||||
<string name="pref_title_hide_log_box">隐藏设备页日志框</string>
|
<string name="pref_title_hide_log_box">隐藏设备页日志框</string>
|
||||||
<string name="pref_summary_hide_log_box">隐藏设备页最下方的日志框</string>
|
<string name="pref_summary_hide_log_box">隐藏设备页最下方的日志框</string>
|
||||||
|
<string name="pref_title_language">语言</string>
|
||||||
|
<string name="pref_summary_language">应用显示语言</string>
|
||||||
|
|
||||||
<!-- Terminal -->
|
<!-- Terminal -->
|
||||||
<string name="terminal_title">终端</string>
|
<string name="terminal_title">终端</string>
|
||||||
@@ -551,4 +553,9 @@
|
|||||||
<string name="vm_mdns_updated">mDNS 发现新端口,已更新快速设备:%1$s:%2$s -> %1$s:%3$s</string>
|
<string name="vm_mdns_updated">mDNS 发现新端口,已更新快速设备:%1$s:%2$s -> %1$s:%3$s</string>
|
||||||
<string name="vm_quick_probe_success">ADB 快速探测连接成功:%1$s:%2$s</string>
|
<string name="vm_quick_probe_success">ADB 快速探测连接成功:%1$s:%2$s</string>
|
||||||
<string name="vm_device_switched_profile">当前连接设备已切换为配置:%1$s</string>
|
<string name="vm_device_switched_profile">当前连接设备已切换为配置:%1$s</string>
|
||||||
|
|
||||||
|
<string name="language_follow_system">跟随系统</string>
|
||||||
|
<string name="language_english">英语</string>
|
||||||
|
<string name="language_chinese">中文</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -246,6 +246,8 @@
|
|||||||
<string name="pref_summary_clear_logs_on_exit">Clear logs when double-pressing back to exit the app</string>
|
<string name="pref_summary_clear_logs_on_exit">Clear logs when double-pressing back to exit the app</string>
|
||||||
<string name="pref_title_hide_log_box">Hide device page log box</string>
|
<string name="pref_title_hide_log_box">Hide device page log box</string>
|
||||||
<string name="pref_summary_hide_log_box">Hide the log box at the bottom of the device page</string>
|
<string name="pref_summary_hide_log_box">Hide the log box at the bottom of the device page</string>
|
||||||
|
<string name="pref_title_language">Language</string>
|
||||||
|
<string name="pref_summary_language">App display language</string>
|
||||||
|
|
||||||
<!-- Terminal -->
|
<!-- Terminal -->
|
||||||
<string name="terminal_title">Terminal</string>
|
<string name="terminal_title">Terminal</string>
|
||||||
@@ -551,4 +553,9 @@
|
|||||||
<string name="vm_mdns_updated">mDNS discovered new port, updated quick device: %1$s:%2$s -> %1$s:%3$s</string>
|
<string name="vm_mdns_updated">mDNS discovered new port, updated quick device: %1$s:%2$s -> %1$s:%3$s</string>
|
||||||
<string name="vm_quick_probe_success">ADB quick probe connection succeeded: %1$s:%2$s</string>
|
<string name="vm_quick_probe_success">ADB quick probe connection succeeded: %1$s:%2$s</string>
|
||||||
<string name="vm_device_switched_profile">Current connected device switched to profile: %1$s</string>
|
<string name="vm_device_switched_profile">Current connected device switched to profile: %1$s</string>
|
||||||
|
|
||||||
|
<string name="language_follow_system">Follow system</string>
|
||||||
|
<string name="language_english">English</string>
|
||||||
|
<string name="language_chinese">Chinese</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Submodule submodule/miuix updated: 81ad71b1c6...127d10c6cb
Reference in New Issue
Block a user