From 56c724d282c55cfb68266934761ed71b6e49d33f Mon Sep 17 00:00:00 2001 From: Miuzarte <982809597@qq.com> Date: Sun, 31 May 2026 17:48:05 +0800 Subject: [PATCH] chore: format codes --- .../miuzarte/scrcpyforandroid/MainActivity.kt | 2 +- .../scrcpyforandroid/NativeCoreFacade.kt | 23 +++-- .../scrcpyforandroid/StreamActivity.kt | 2 +- .../constants/ScrcpyPresets.kt | 2 +- .../miuix/OverlaySpinnerPreference.kt | 17 +--- .../scrcpyforandroid/miuix/SpinnerItemImpl.kt | 10 +- .../scrcpyforandroid/models/DeviceModels.kt | 8 +- .../nativecore/AdbMdnsDiscoverer.kt | 6 +- .../nativecore/AdbPairingTypes.kt | 12 +-- .../nativecore/AnnexBDecoder.kt | 6 +- .../nativecore/DirectAdbClient.kt | 46 ++++----- .../nativecore/DirectAdbPairingClient.kt | 2 +- .../nativecore/NativeAdbService.kt | 2 +- .../nativecore/PersistentVideoRenderer.kt | 63 ++++++------- .../nativecore/ScrcpyAudioPlayer.kt | 21 ++--- .../pages/DeviceTabViewModel.kt | 70 +++++--------- .../pages/FileManagerViewModel.kt | 27 ++---- .../pages/FullscreenControlScreen.kt | 71 +++++--------- .../pages/RecordPreferencesScreen.kt | 44 ++------- .../pages/ReorderDevicesScreen.kt | 16 +--- .../scrcpyforandroid/pages/StreamScreen.kt | 11 +-- .../scrcpyforandroid/pages/TerminalScreen.kt | 51 +++------- .../pages/TerminalViewModel.kt | 8 +- .../pages/effect/BgEffectConfigOs2.kt | 8 +- .../pages/effect/BgEffectConfigOs3.kt | 24 ++--- .../pages/effect/FrameTime.kt | 8 +- .../password/BiometricGate.kt | 6 +- .../password/PasswordPickerPopup.kt | 13 +-- .../password/PasswordRepository.kt | 5 +- .../password/PasswordUseCase.kt | 2 +- .../scrcpyforandroid/scaffolds/ArrowSlider.kt | 12 +-- .../scrcpyforandroid/scaffolds/LazyColumn.kt | 14 +-- .../scaffolds/OverlaySpinnerWithFallback.kt | 10 +- .../scaffolds/ReorderableList.kt | 28 ++---- .../scaffolds/SuperTextField.kt | 8 +- .../scrcpyforandroid/scrcpy/ClientOptions.kt | 69 ++++++-------- .../scrcpyforandroid/scrcpy/Scrcpy.kt | 84 +++++++---------- .../scrcpyforandroid/scrcpy/ServerParams.kt | 11 +-- .../scrcpy/TouchEventHandler.kt | 16 ++-- .../scrcpyforandroid/services/AppRuntime.kt | 1 - .../services/AppUpdateChecker.kt | 8 +- .../services/DeviceAdbAutoReconnectManager.kt | 4 +- .../services/DeviceAdbBackgroundRunner.kt | 8 +- .../DeviceAdbConnectionCoordinator.kt | 2 +- .../services/DeviceConnectionLogic.kt | 2 +- .../scrcpyforandroid/services/EventLogger.kt | 4 +- .../services/FileManagerService.kt | 33 +++---- .../PictureInPictureActionReceiver.kt | 2 +- .../scrcpyforandroid/services/PublicDirs.kt | 4 +- .../scrcpyforandroid/storage/AdbClientData.kt | 4 +- .../scrcpyforandroid/storage/AppSettings.kt | 12 +-- .../scrcpyforandroid/storage/BundleSync.kt | 26 +----- .../scrcpyforandroid/storage/QuickDevices.kt | 4 +- .../scrcpyforandroid/storage/ScrcpyOptions.kt | 21 +---- .../storage/ScrcpyProfiles.kt | 16 ++-- .../scrcpyforandroid/storage/Settings.kt | 31 ++----- .../scrcpyforandroid/ui/ThemePreferences.kt | 6 +- .../ui/component/FloatingBottomBar.kt | 61 ++++-------- .../miuix/animation/DampedDragAnimation.kt | 6 +- .../miuix/animation/InteractiveHighlight.kt | 8 +- .../miuix/modifier/DragGestureInspector.kt | 10 +- .../widgets/AppBottomSheets.kt | 14 +-- .../widgets/ScrcpyInputSurfaceView.kt | 4 +- .../widgets/StatusCardModels.kt | 17 +--- .../widgets/TerminalInputView.kt | 4 +- .../widgets/VirtualButtons.kt | 93 ++++++------------- 66 files changed, 422 insertions(+), 821 deletions(-) diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/MainActivity.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/MainActivity.kt index e2ca937..544e8f3 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/MainActivity.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/MainActivity.kt @@ -21,7 +21,7 @@ import kotlinx.coroutines.runBlocking import java.util.Locale // 生物认证需要 FragmentActivity -class MainActivity : FragmentActivity() { +class MainActivity: FragmentActivity() { override fun attachBaseContext(newBase: Context) { val languageTag = getAppLanguageTag(newBase) diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/NativeCoreFacade.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/NativeCoreFacade.kt index 8dd7326..ff268cb 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/NativeCoreFacade.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/NativeCoreFacade.kt @@ -11,7 +11,6 @@ import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Codec import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -89,7 +88,10 @@ object NativeCoreFacade { } } if (session.width <= 0 || session.height <= 0) { - Log.i(TAG, "attachVideoSurface(): defer decoder, session size not yet known (${session.width}x${session.height})") + Log.i( + TAG, + "attachVideoSurface(): defer decoder, session size not yet known (${session.width}x${session.height})", + ) return } createOrReplaceDecoder(session) @@ -112,13 +114,13 @@ object NativeCoreFacade { if (requestId != null && currentId != null && requestId != currentId) { Log.i( TAG, - "detachVideoSurface(): skip stale request requestSurfaceId=$requestId currentSurfaceId=$currentId" + "detachVideoSurface(): skip stale request requestSurfaceId=$requestId currentSurfaceId=$currentId", ) return } Log.i( TAG, - "detachVideoSurface(): surfaceId=$requestId releaseDecoder=$releaseDecoder" + "detachVideoSurface(): surfaceId=$requestId releaseDecoder=$releaseDecoder", ) activeSurfaceId = null renderer.detachDisplaySurface(surface, releaseSurface = false) @@ -197,7 +199,7 @@ object NativeCoreFacade { if (packetCount == 1L || packetCount % 120L == 0L) { Log.i( TAG, - "videoFeed(): packets=$packetCount key=${packet.isKeyFrame} cfg=${packet.isConfig} decoder=${decoder != null}" + "videoFeed(): packets=$packetCount key=${packet.isKeyFrame} cfg=${packet.isConfig} decoder=${decoder != null}", ) } @@ -207,7 +209,7 @@ object NativeCoreFacade { packet.data, packet.ptsUs, packet.isKeyFrame, - packet.isConfig + packet.isConfig, ) } } @@ -233,7 +235,10 @@ object NativeCoreFacade { (info.width != currentSessionInfo!!.width || info.height != currentSessionInfo!!.height) ) { // Flex display: rebuild decoder on size change - Log.i(TAG, "onVideoSizeChanged(): rebuild decoder ${currentSessionInfo!!.width}x${currentSessionInfo!!.height} → ${info.width}x${info.height}") + Log.i( + TAG, + "onVideoSizeChanged(): rebuild decoder ${currentSessionInfo!!.width}x${currentSessionInfo!!.height} → ${info.width}x${info.height}", + ) currentSessionInfo = info createOrReplaceDecoder(info) } @@ -306,7 +311,7 @@ object NativeCoreFacade { "createOrReplaceDecoder(): " + "codec=${session.codec?.string ?: "null"}, " + "size=${session.width}x${session.height}, " + - "persistent=true" + "persistent=true", ) val newDecoder = AnnexBDecoder( width = session.width, @@ -325,7 +330,7 @@ object NativeCoreFacade { } Log.i( TAG, - "videoSizeChanged(): ${current.width}x${current.height} -> ${width}x${height}" + "videoSizeChanged(): ${current.width}x${current.height} -> ${width}x${height}", ) currentSessionInfo = current.copy(width = width, height = height) mainHandler.post { diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/StreamActivity.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/StreamActivity.kt index b063193..367bf77 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/StreamActivity.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/StreamActivity.kt @@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import java.lang.ref.WeakReference -class StreamActivity : FragmentActivity() { +class StreamActivity: FragmentActivity() { private val basicPip = BasicPictureInPicture(this) private val pipActionReceiver = PictureInPictureActionReceiver() diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/ScrcpyPresets.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/ScrcpyPresets.kt index 7532014..f0af1c3 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/ScrcpyPresets.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/constants/ScrcpyPresets.kt @@ -7,7 +7,7 @@ package io.github.miuzarte.scrcpyforandroid.constants * @param T The type of preset values (typically Int) * @param values The list of preset values */ -class Preset>(val values: List) { +class Preset>(val values: List) { val lastIndex: Int get() = values.lastIndex val size: Int get() = values.size val indices: IntRange get() = values.indices diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/OverlaySpinnerPreference.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/OverlaySpinnerPreference.kt index 50aa832..36cf741 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/OverlaySpinnerPreference.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/OverlaySpinnerPreference.kt @@ -3,12 +3,7 @@ package io.github.miuzarte.scrcpyforandroid.miuix import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.key -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.ui.Alignment import androidx.compose.ui.Modifier @@ -18,15 +13,7 @@ import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import top.yukonga.miuix.kmp.basic.BasicComponent -import top.yukonga.miuix.kmp.basic.BasicComponentColors -import top.yukonga.miuix.kmp.basic.BasicComponentDefaults -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.PopupPositionProvider -import top.yukonga.miuix.kmp.basic.Text +import top.yukonga.miuix.kmp.basic.* import top.yukonga.miuix.kmp.overlay.OverlayListPopup import top.yukonga.miuix.kmp.theme.MiuixTheme diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/SpinnerItemImpl.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/SpinnerItemImpl.kt index 1275996..06b3c8e 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/SpinnerItemImpl.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/miuix/SpinnerItemImpl.kt @@ -2,15 +2,7 @@ package io.github.miuzarte.scrcpyforandroid.miuix import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.sizeIn -import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberUpdatedState diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/models/DeviceModels.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/models/DeviceModels.kt index 3089b42..89766b0 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/models/DeviceModels.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/models/DeviceModels.kt @@ -6,7 +6,7 @@ import io.github.miuzarte.scrcpyforandroid.storage.ScrcpyOptions import kotlinx.parcelize.Parcelize // Composable 用, 不可变 List -class DeviceShortcuts(val devices: List) : List by devices { +class DeviceShortcuts(val devices: List): List by devices { fun marshalToString( separator: String = DEFAULT_SEPARATOR, ): String = joinToString(separator) { it.marshalToString() } @@ -97,7 +97,7 @@ class DeviceShortcuts(val devices: List) : List || (newPort != null && newPort != old.port) ) newList.distinctBy { it.id } - else newList + else newList, ) } @@ -176,7 +176,7 @@ data class DeviceShortcut( if (openFullscreenOnStart) "1" else "0", scrcpyProfileId.trim(), ).joinToString( - separator = separator + separator = separator, ) companion object { @@ -259,7 +259,7 @@ data class DeviceShortcut( data class ConnectionTarget( val host: String, val port: Int = Defaults.ADB_PORT, -) : Parcelable { +): Parcelable { override fun toString(): String = if (':' in host) "[$host]:$port" else "$host:$port" diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbMdnsDiscoverer.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbMdnsDiscoverer.kt index 0831004..d07eb0d 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbMdnsDiscoverer.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbMdnsDiscoverer.kt @@ -2,9 +2,9 @@ package io.github.miuzarte.scrcpyforandroid.nativecore import android.annotation.SuppressLint import android.content.Context -import android.os.Build import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo +import android.os.Build import android.util.Log import java.io.IOException import java.net.InetSocketAddress @@ -56,7 +56,7 @@ internal object AdbMdnsDiscoverer { val discoveryFinished = AtomicBoolean(false) val latch = CountDownLatch(1) - val discoveryListener = object : NsdManager.DiscoveryListener { + val discoveryListener = object: NsdManager.DiscoveryListener { override fun onDiscoveryStarted(serviceType: String) { Log.v(TAG, "discovery started: $serviceType") } @@ -79,7 +79,7 @@ internal object AdbMdnsDiscoverer { override fun onServiceFound(serviceInfo: NsdServiceInfo) { if (discoveryFinished.get()) return Log.v(TAG, "service found: ${serviceInfo.serviceName}") - val resolveListener = object : NsdManager.ResolveListener { + val resolveListener = object: NsdManager.ResolveListener { override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) { Log.v(TAG, "resolve failed: ${serviceInfo.serviceName}, error=$errorCode") } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbPairingTypes.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbPairingTypes.kt index f577722..835972c 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbPairingTypes.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AdbPairingTypes.kt @@ -11,11 +11,7 @@ import java.math.BigInteger import java.net.Socket import java.nio.ByteBuffer import java.nio.ByteOrder -import java.security.KeyFactory -import java.security.PrivateKey -import java.security.Provider -import java.security.SecureRandom -import java.security.Security +import java.security.* import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import java.security.interfaces.RSAPrivateKey @@ -73,7 +69,7 @@ internal class AdbPairingKey( } private val keyManager: X509ExtendedKeyManager - get() = object : X509ExtendedKeyManager() { + get() = object: X509ExtendedKeyManager() { private val keyAlias = "adbkey" override fun chooseClientAlias( @@ -110,7 +106,7 @@ internal class AdbPairingKey( @get:SuppressLint("CustomX509TrustManager") @get:Suppress("TrustAllX509TrustManager") private val trustManager: X509ExtendedTrustManager - get() = object : X509ExtendedTrustManager() { + get() = object: X509ExtendedTrustManager() { // ADB pairing uses SPAKE2 + exported keying material to authenticate the peer. // The peer cert is ephemeral/self-signed, so PKIX validation is intentionally bypassed here. private fun acceptForPairing( @@ -213,4 +209,4 @@ private fun RSAPublicKey.adbEncoded(name: String): ByteArray { /** * Thrown when the supplied pairing code is invalid during the pairing flow. */ -internal class AdbInvalidPairingCodeException : Exception() +internal class AdbInvalidPairingCodeException: Exception() diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AnnexBDecoder.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AnnexBDecoder.kt index c8bbe94..5182ce6 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AnnexBDecoder.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/AnnexBDecoder.kt @@ -94,14 +94,14 @@ class AnnexBDecoder( if (inCount == 1L || inCount % 180L == 0L || isConfig) { Log.i( TAG, - "feed(): mime=$decoderMime in=$inCount size=${data.size} key=$isKeyFrame cfg=$isConfig pts=$ptsUs" + "feed(): mime=$decoderMime in=$inCount size=${data.size} key=$isKeyFrame cfg=$isConfig pts=$ptsUs", ) } } else { if (isConfig || isKeyFrame) { Log.w( TAG, - "drop critical packet: mime=$decoderMime size=${data.size} key=$isKeyFrame cfg=$isConfig" + "drop critical packet: mime=$decoderMime size=${data.size} key=$isKeyFrame cfg=$isConfig", ) } } @@ -110,7 +110,7 @@ class AnnexBDecoder( Log.w( TAG, "feed failed: mime=$decoderMime size=${data.size} key=$isKeyFrame cfg=$isConfig", - it + it, ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbClient.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbClient.kt index c87d3f9..31e2516 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbClient.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbClient.kt @@ -7,24 +7,13 @@ import io.github.miuzarte.scrcpyforandroid.storage.AdbClientData import io.github.miuzarte.scrcpyforandroid.storage.AppSettings import io.github.miuzarte.scrcpyforandroid.storage.Storage import kotlinx.coroutines.runBlocking -import java.io.BufferedInputStream -import java.io.ByteArrayOutputStream -import java.io.Closeable -import java.io.EOFException -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream +import java.io.* import java.math.BigInteger import java.net.InetSocketAddress import java.net.Socket import java.nio.ByteBuffer import java.nio.ByteOrder -import java.security.KeyFactory -import java.security.KeyPairGenerator -import java.security.MessageDigest -import java.security.PrivateKey -import java.security.PublicKey -import java.security.Signature +import java.security.* import java.security.interfaces.RSAPrivateCrtKey import java.security.interfaces.RSAPublicKey import java.security.spec.PKCS8EncodedKeySpec @@ -72,7 +61,8 @@ internal object DirectAdbTransport { port, privateKey, publicKeyX509, - keyName.ifBlank { AppSettings.ADB_KEY_NAME.defaultValue }) + keyName.ifBlank { AppSettings.ADB_KEY_NAME.defaultValue }, + ) conn.handshake() Log.i(TAG, "connect(): handshake success for $host:$port") return conn @@ -186,7 +176,7 @@ internal object DirectAdbTransport { importedPrivateKeyFileName = "", importedPublicKeyX509 = "", importedPublicKeyFileName = "", - ) + ), ) loadOrCreate() }.also { cachedKeys = it } @@ -232,21 +222,21 @@ internal object DirectAdbTransport { current.copy( rsaPublicKeyX509 = encoded, ) - } + }, ) } Log.i( TAG, "loadOrCreate(): loaded persisted RSA key pair from DataStore, " + - "fp=${fingerprint(pub)}" + "fp=${fingerprint(pub)}", ) return Pair(priv, pub) } catch (e: Exception) { Log.w( TAG, "loadOrCreate(): failed to load persisted key from DataStore, regenerating", - e + e, ) } } @@ -264,12 +254,12 @@ internal object DirectAdbTransport { importedPrivateKeyFileName = "", importedPublicKeyX509 = "", importedPublicKeyFileName = "", - ) + ), ) Log.i( TAG, - "loadOrCreate(): generated new RSA key pair, fp=${fingerprint(kp.public.encoded)}" + "loadOrCreate(): generated new RSA key pair, fp=${fingerprint(kp.public.encoded)}", ) return Pair(kp.private, kp.public.encoded) } @@ -427,7 +417,7 @@ internal object DirectAdbTransport { val exponent = buf.int.toLong() and 0xffffffffL val modulus = BigInteger(1, modulusLE.reversedArray()) return KeyFactory.getInstance("RSA").generatePublic( - RSAPublicKeySpec(modulus, BigInteger.valueOf(exponent)) + RSAPublicKeySpec(modulus, BigInteger.valueOf(exponent)), ) } @@ -538,7 +528,7 @@ internal class DirectAdbConnection( private val privateKey: PrivateKey, private val publicKeyX509: ByteArray, private val keyName: String = AppSettings.ADB_KEY_NAME.defaultValue, -) : AutoCloseable { +): AutoCloseable { private val sha1DigestInfoPrefix = byteArrayOf( 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, @@ -623,9 +613,9 @@ internal class DirectAdbConnection( else -> throw IOException( "ADB: unexpected message 0x${ afterSign.command.toString( - 16 + 16, ) - } after AUTH_SIGNATURE" + } after AUTH_SIGNATURE", ) } } @@ -837,7 +827,7 @@ internal class DirectAdbConnection( command: Int, arg0: Int = 0, arg1: Int = 0, - data: ByteArray = ByteArray(0) + data: ByteArray = ByteArray(0), ) { val crc = data.fold(0L) { acc, b -> acc + (b.toLong() and 0xFF) }.toInt() val header = ByteBuffer.allocate(24).order(ByteOrder.LITTLE_ENDIAN) @@ -957,7 +947,7 @@ internal class DirectAdbConnection( class AdbSocketStream( val localId: Int, private val sender: (cmd: Int, arg0: Int, arg1: Int, `data`: ByteArray) -> Unit, -) : Closeable { +): Closeable { companion object { private const val A_WRTE = 0x45545257 @@ -1016,7 +1006,7 @@ class AdbSocketStream( queue.offer(EndOfStreamMarker) } - private inner class InStream : InputStream() { + private inner class InStream: InputStream() { private var chunk: ByteArray? = null private var off = 0 @@ -1047,7 +1037,7 @@ class AdbSocketStream( override fun available(): Int = chunk?.let { it.size - off } ?: 0 } - private inner class OutStream : OutputStream() { + private inner class OutStream: OutputStream() { override fun write(b: Int) = write(byteArrayOf(b.toByte())) override fun write(b: ByteArray, off: Int, len: Int) { if (closed) throw IOException("ADB stream closed") diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbPairingClient.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbPairingClient.kt index 0cfbf05..1d5c063 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbPairingClient.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/DirectAdbPairingClient.kt @@ -134,7 +134,7 @@ internal class DirectAdbPairingClient( private val port: Int, private val pairingCode: String, private val key: AdbPairingKey, -) : Closeable { +): Closeable { private enum class State { READY, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/NativeAdbService.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/NativeAdbService.kt index 5e61de8..806afc3 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/NativeAdbService.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/NativeAdbService.kt @@ -190,7 +190,7 @@ object NativeAdbService { .map(String::trim) .lastOrNull { '/' in it } ?: throw IllegalStateException( - "Cannot resolve launch activity for $normalizedPackageName" + "Cannot resolve launch activity for $normalizedPackageName", ) val displayArg = displayId diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/PersistentVideoRenderer.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/PersistentVideoRenderer.kt index 277e716..a560b9f 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/PersistentVideoRenderer.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/PersistentVideoRenderer.kt @@ -1,15 +1,7 @@ package io.github.miuzarte.scrcpyforandroid.nativecore import android.graphics.SurfaceTexture -import android.opengl.EGL14 -import android.opengl.EGLConfig -import android.opengl.EGLContext -import android.opengl.EGLDisplay -import android.opengl.EGLExt -import android.opengl.EGLSurface -import android.opengl.GLES11Ext -import android.opengl.GLES20 -import android.opengl.Matrix +import android.opengl.* import android.os.Handler import android.os.HandlerThread import android.util.Log @@ -85,7 +77,7 @@ class PersistentVideoRenderer { eglConfig, surface, intArrayOf(EGL14.EGL_NONE), - 0 + 0, ) Log.i(tag, "attachDisplaySurface(): attached surfaceId=$newId") drawFrame() @@ -96,7 +88,7 @@ class PersistentVideoRenderer { val requestId = surface?.let { System.identityHashCode(it) } Log.i( tag, - "detachDisplaySurface(): request surfaceId=$requestId releaseSurface=$releaseSurface current=${displaySurfaceId}" + "detachDisplaySurface(): request surfaceId=$requestId releaseSurface=$releaseSurface current=${displaySurfaceId}", ) handler.post { if (released) return@post @@ -137,7 +129,7 @@ class PersistentVideoRenderer { eglConfig, surface, intArrayOf(EGL14.EGL_NONE), - 0 + 0, ) Log.i(tag, "attachRecordSurface(): attached surfaceId=$newId") drawFrame() @@ -148,7 +140,7 @@ class PersistentVideoRenderer { val requestId = surface?.let { System.identityHashCode(it) } Log.i( tag, - "detachRecordSurface(): request surfaceId=$requestId releaseSurface=$releaseSurface current=$recordSurfaceId" + "detachRecordSurface(): request surfaceId=$requestId releaseSurface=$releaseSurface current=$recordSurfaceId", ) handler.post { if (released) return@post @@ -183,7 +175,7 @@ class PersistentVideoRenderer { eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, - EGL14.EGL_NO_CONTEXT + EGL14.EGL_NO_CONTEXT, ) if (eglPbufferSurface != EGL14.EGL_NO_SURFACE) { EGL14.eglDestroySurface(eglDisplay, eglPbufferSurface) @@ -227,7 +219,7 @@ class PersistentVideoRenderer { EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_ALPHA_SIZE, 8, - EGL14.EGL_NONE + EGL14.EGL_NONE, ) check(EGL14.eglChooseConfig(eglDisplay, attribs, 0, configs, 0, 1, numConfigs, 0)) eglConfig = configs[0] @@ -236,30 +228,33 @@ class PersistentVideoRenderer { eglConfig, EGL14.EGL_NO_CONTEXT, intArrayOf(0x3098, 2, EGL14.EGL_NONE), - 0 + 0, ) check(eglContext != EGL14.EGL_NO_CONTEXT) eglPbufferSurface = EGL14.eglCreatePbufferSurface( eglDisplay, eglConfig, intArrayOf(EGL14.EGL_WIDTH, 1, EGL14.EGL_HEIGHT, 1, EGL14.EGL_NONE), - 0 + 0, ) check(eglPbufferSurface != EGL14.EGL_NO_SURFACE) check(EGL14.eglMakeCurrent(eglDisplay, eglPbufferSurface, eglPbufferSurface, eglContext)) oesTextureId = createExternalTexture() decoderSurfaceTexture = SurfaceTexture(oesTextureId).apply { - setOnFrameAvailableListener({ - val n = frameAvailableCount.incrementAndGet() - if (n == 1L || n % 120L == 0L) { - Log.i( - tag, - "onFrameAvailable(): available=$n consumed=${frameConsumedCount.get()} rendered=${frameRenderedCount.get()} display=${displaySurfaceId != null}" - ) - } - drawFrame() - }, handler) + setOnFrameAvailableListener( + { + val n = frameAvailableCount.incrementAndGet() + if (n == 1L || n % 120L == 0L) { + Log.i( + tag, + "onFrameAvailable(): available=$n consumed=${frameConsumedCount.get()} rendered=${frameRenderedCount.get()} display=${displaySurfaceId != null}", + ) + } + drawFrame() + }, + handler, + ) } decoderSurface = Surface(decoderSurfaceTexture) Log.i(tag, "initializeLocked(): decoder surface created") @@ -290,7 +285,7 @@ class PersistentVideoRenderer { if (consumed == 1L || consumed % 120L == 0L) { Log.i( tag, - "drawFrame(): consumed=$consumed available=${frameAvailableCount.get()} rendered=${frameRenderedCount.get()} display=${displaySurfaceId != null}" + "drawFrame(): consumed=$consumed available=${frameAvailableCount.get()} rendered=${frameRenderedCount.get()} display=${displaySurfaceId != null}", ) } } @@ -322,7 +317,7 @@ class PersistentVideoRenderer { if (rendered == 1L || rendered % 120L == 0L) { Log.i( tag, - "drawFrame(): rendered=$rendered consumed=${frameConsumedCount.get()} available=${frameAvailableCount.get()} viewport=${width[0]}x${height[0]}" + "drawFrame(): rendered=$rendered consumed=${frameConsumedCount.get()} available=${frameAvailableCount.get()} viewport=${width[0]}x${height[0]}", ) } } @@ -391,22 +386,22 @@ class PersistentVideoRenderer { GLES20.glTexParameteri( GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, - GLES20.GL_LINEAR + GLES20.GL_LINEAR, ) GLES20.glTexParameteri( GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, - GLES20.GL_LINEAR + GLES20.GL_LINEAR, ) GLES20.glTexParameteri( GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, - GLES20.GL_CLAMP_TO_EDGE + GLES20.GL_CLAMP_TO_EDGE, ) GLES20.glTexParameteri( GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, - GLES20.GL_CLAMP_TO_EDGE + GLES20.GL_CLAMP_TO_EDGE, ) return textures[0] } @@ -439,7 +434,7 @@ class PersistentVideoRenderer { 1f, -1f, 1f, 1f, -1f, 1f, 0f, 0f, 1f, 1f, 1f, 0f, - ) + ), ) position(0) } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/ScrcpyAudioPlayer.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/ScrcpyAudioPlayer.kt index 0fb3fc9..edba3a5 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/ScrcpyAudioPlayer.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/nativecore/ScrcpyAudioPlayer.kt @@ -3,12 +3,7 @@ package io.github.miuzarte.scrcpyforandroid.nativecore // Go reader note: Audio output helper for scrcpy stream: decodes/plays PCM or codec audio frames. import android.content.Context -import android.media.AudioAttributes -import android.media.AudioFormat -import android.media.AudioManager -import android.media.AudioTrack -import android.media.MediaCodec -import android.media.MediaFormat +import android.media.* import android.os.Build import android.util.Log import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Codec @@ -54,7 +49,7 @@ class ScrcpyAudioPlayer( TAG, "feedPacket(): config packet size=${data.size} codec=0x${ codecId.toUInt().toString(16) - }" + }", ) when (codecId) { Codec.OPUS.id -> prepareOpus(data) @@ -101,7 +96,7 @@ class ScrcpyAudioPlayer( val format = MediaFormat.createAudioFormat( MediaFormat.MIMETYPE_AUDIO_OPUS, SAMPLE_RATE, - CHANNELS + CHANNELS, ) format.setByteBuffer("csd-0", ByteBuffer.wrap(opusHead)) // pre-skip field: 2 bytes LE at offset 10 of the OpusHead @@ -132,7 +127,7 @@ class ScrcpyAudioPlayer( val format = MediaFormat.createAudioFormat( MediaFormat.MIMETYPE_AUDIO_FLAC, SAMPLE_RATE, - CHANNELS + CHANNELS, ) if (flacConfig.isNotEmpty()) { format.setByteBuffer("csd-0", ByteBuffer.wrap(flacConfig)) @@ -196,11 +191,11 @@ class ScrcpyAudioPlayer( val attributesBuilder = AudioAttributes.Builder() .setUsage( if (lowLatency) AudioAttributes.USAGE_GAME - else AudioAttributes.USAGE_MEDIA + else AudioAttributes.USAGE_MEDIA, ) .setContentType( if (lowLatency) AudioAttributes.CONTENT_TYPE_SONIFICATION - else AudioAttributes.CONTENT_TYPE_MOVIE + else AudioAttributes.CONTENT_TYPE_MOVIE, ) if (lowLatency) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { @@ -215,7 +210,7 @@ class ScrcpyAudioPlayer( .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setSampleRate(SAMPLE_RATE) .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) - .build() + .build(), ) .setBufferSizeInBytes(bufferSize) .setTransferMode(AudioTrack.MODE_STREAM) @@ -229,7 +224,7 @@ class ScrcpyAudioPlayer( Log.i( TAG, "low-latency audio requested: nativeSampleRate=$nativeSampleRate streamSampleRate=$SAMPLE_RATE " + - "framesPerBurst=$framesPerBurst bufferSize=$bufferSize performanceMode=${track.performanceMode}" + "framesPerBurst=$framesPerBurst bufferSize=$bufferSize performanceMode=${track.performanceMode}", ) } return track diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabViewModel.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabViewModel.kt index 8de1379..a218e56 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabViewModel.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/DeviceTabViewModel.kt @@ -11,13 +11,8 @@ import io.github.miuzarte.scrcpyforandroid.models.ConnectionTarget import io.github.miuzarte.scrcpyforandroid.models.DeviceShortcut import io.github.miuzarte.scrcpyforandroid.models.DeviceShortcuts 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.DisconnectCause -import io.github.miuzarte.scrcpyforandroid.services.EventLogMessage +import io.github.miuzarte.scrcpyforandroid.services.* import io.github.miuzarte.scrcpyforandroid.services.EventLogger.logEvent -import io.github.miuzarte.scrcpyforandroid.services.LocalInputService -import io.github.miuzarte.scrcpyforandroid.services.render import io.github.miuzarte.scrcpyforandroid.storage.AppSettings import io.github.miuzarte.scrcpyforandroid.storage.ScrcpyOptions import io.github.miuzarte.scrcpyforandroid.storage.Settings @@ -27,25 +22,9 @@ import io.github.miuzarte.scrcpyforandroid.storage.Storage.scrcpyOptions import io.github.miuzarte.scrcpyforandroid.storage.Storage.scrcpyProfiles import io.github.miuzarte.scrcpyforandroid.widgets.VirtualButtonAction import io.github.miuzarte.scrcpyforandroid.widgets.VirtualButtonActions -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.receiveAsFlow -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext +import kotlinx.coroutines.flow.* private const val ADB_CONNECT_TIMEOUT_MS = 12_000L private const val ADB_KEEPALIVE_INTERVAL_MS = 3_000L @@ -58,7 +37,7 @@ private const val ADB_TCP_PROBE_TIMEOUT_MS = 500 internal class DeviceTabViewModel( internal val scrcpy: Scrcpy, connectionServices: DeviceConnectionServices, -) : ViewModel() { +): ViewModel() { val scrcpyListings: Scrcpy.Listings get() = scrcpy.listings @@ -107,7 +86,7 @@ internal class DeviceTabViewModel( val quickConnectInput: StateFlow = _quickConnectInput.asStateFlow() private val _savedShortcuts = MutableStateFlow( - DeviceShortcuts.unmarshalFrom(_qdBundle.value.quickDevicesList) + DeviceShortcuts.unmarshalFrom(_qdBundle.value.quickDevicesList), ) val savedShortcuts: StateFlow = _savedShortcuts.asStateFlow() @@ -223,13 +202,13 @@ internal class DeviceTabViewModel( val virtualButtonLayout: StateFlow, List>> = _asBundle.map { VirtualButtonActions.splitLayout( - VirtualButtonActions.parseStoredLayout(it.virtualButtonsLayout) + VirtualButtonActions.parseStoredLayout(it.virtualButtonsLayout), ) }.stateIn( viewModelScope, SharingStarted.Eagerly, VirtualButtonActions.splitLayout( - VirtualButtonActions.parseStoredLayout(_asBundle.value.virtualButtonsLayout) + VirtualButtonActions.parseStoredLayout(_asBundle.value.virtualButtonsLayout), ), ) @@ -397,7 +376,7 @@ internal class DeviceTabViewModel( EventLogMessage.Resource( R.string.vm_send_action, listOf(EventLogMessage.Resource(action.titleResId)), - ) + ), ) { scrcpy.injectKeycode(0, keycode) scrcpy.injectKeycode(1, keycode) @@ -432,7 +411,7 @@ internal class DeviceTabViewModel( private fun runBusy( label: EventLogMessage, onFinished: (() -> Unit)? = null, - block: suspend () -> Unit + block: suspend () -> Unit, ) { if (_busy.value) return viewModelScope.launch { @@ -492,7 +471,7 @@ internal class DeviceTabViewModel( val result = connectionController.disconnectAdbConnection( clearQuickOnlineForTarget, cause, - statusLine + statusLine, ) result.clearedTarget?.let { target -> if (target.host.isNotBlank()) @@ -535,14 +514,14 @@ internal class DeviceTabViewModel( host = host, port = port, name = fullLabel, - updateNameOnlyWhenEmpty = true + updateNameOnlyWhenEmpty = true, ) } logEvent( "ADB connected: model=${info.model}, serial=${info.serial.ifBlank { "unknown" }}, " + "manufacturer=${info.manufacturer.ifBlank { "unknown" }}, brand=${info.brand.ifBlank { "unknown" }}, " + - "device=${info.device.ifBlank { "unknown" }}, android=${info.androidRelease.ifBlank { "unknown" }}, sdk=${info.sdkInt}" + "device=${info.device.ifBlank { "unknown" }}, android=${info.androidRelease.ifBlank { "unknown" }}, sdk=${info.sdkInt}", ) AppRuntime.snackbar(R.string.vm_adb_connected) @@ -607,7 +586,8 @@ internal class DeviceTabViewModel( if (!resolvedOptions.video) "off" else { val codec = session.codec?.string ?: "null" - val sizeHint = if (session.width > 0 && session.height > 0) " ${session.width}x${session.height}" else "" + val sizeHint = + if (session.width > 0 && session.height > 0) " ${session.width}x${session.height}" else "" val bitrateSuffix = if (activeBundle.videoBitRate <= 0) " @default" else " @%.1fMbps".format(activeBundle.videoBitRate / 1_000_000f) "$codec$sizeHint$bitrateSuffix" @@ -623,11 +603,11 @@ internal class DeviceTabViewModel( logEvent( "scrcpy 已启动: device=${session.deviceName}, video=$videoDetail, audio=$audioDetail, " + "control=${resolvedOptions.control}, turnScreenOff=${resolvedOptions.turnScreenOff}, " + - "maxSize=${resolvedOptions.maxSize}, maxFps=${resolvedOptions.maxFps}" + "maxSize=${resolvedOptions.maxSize}, maxFps=${resolvedOptions.maxFps}", ) AppRuntime.snackbar( if (resolvedOptions.recordFilename.isNotBlank()) R.string.vm_scrcpy_started_recording - else R.string.vm_scrcpy_started + else R.string.vm_scrcpy_started, ) } @@ -699,13 +679,13 @@ internal class DeviceTabViewModel( } logEvent( if (useLegacyPaste) R.string.vm_legacy_paste_injected - else R.string.vm_clipboard_synced_paste + else R.string.vm_clipboard_synced_paste, ) }.onFailure { error -> logEvent(R.string.vm_clipboard_paste_failed, level = Log.WARN, error = error) AppRuntime.snackbar( if (useLegacyPaste) R.string.fullscreen_legacy_paste_failed - else R.string.fullscreen_clipboard_sync_failed + else R.string.fullscreen_clipboard_sync_failed, ) } } @@ -723,7 +703,7 @@ internal class DeviceTabViewModel( ) AppRuntime.snackbar( if (useClipboardPaste) R.string.fullscreen_paste_non_ascii - else R.string.fullscreen_text_input_failed + else R.string.fullscreen_text_input_failed, ) } } @@ -747,7 +727,7 @@ internal class DeviceTabViewModel( port = device.port, autoStartScrcpy = device.startScrcpyOnConnect, autoEnterFullScreen = device.startScrcpyOnConnect && device.openFullscreenOnStart, - scrcpyProfileId = device.scrcpyProfileId + scrcpyProfileId = device.scrcpyProfileId, ) connectionController.updateQuickConnected(false) } catch (error: Exception) { @@ -818,7 +798,7 @@ internal class DeviceTabViewModel( ) AppRuntime.snackbar( if (ok) R.string.vm_pairing_succeeded - else R.string.vm_pairing_failed + else R.string.vm_pairing_failed, ) } } @@ -850,7 +830,7 @@ internal class DeviceTabViewModel( viewModelScope.launch { disconnectAdbConnection( cause = DisconnectCause.KeepAliveFailed, - statusLine = "ADB disconnected" + statusLine = "ADB disconnected", ) } logEvent(R.string.vm_auto_reconnect_failed, level = Log.ERROR, error = error) @@ -979,7 +959,7 @@ internal class DeviceTabViewModel( screenHeight, pressure, actionButton, - buttons + buttons, ) } @@ -1001,9 +981,9 @@ internal class DeviceTabViewModel( class Factory( private val scrcpy: Scrcpy, private val connectionServices: DeviceConnectionServices, - ) : ViewModelProvider.Factory { + ): ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") - override fun create(modelClass: Class): T { + override fun create(modelClass: Class): T { return DeviceTabViewModel(scrcpy, connectionServices) as T } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FileManagerViewModel.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FileManagerViewModel.kt index 3381d3f..7a831ef 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FileManagerViewModel.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FileManagerViewModel.kt @@ -6,24 +6,11 @@ import android.net.Uri import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import io.github.miuzarte.scrcpyforandroid.R -import io.github.miuzarte.scrcpyforandroid.services.AppRuntime -import io.github.miuzarte.scrcpyforandroid.services.DirectoryDownloadSnapshot -import io.github.miuzarte.scrcpyforandroid.services.DirectorySnapshotSession -import io.github.miuzarte.scrcpyforandroid.services.FileManagerService -import io.github.miuzarte.scrcpyforandroid.services.RemoteFileEntry -import io.github.miuzarte.scrcpyforandroid.services.RemoteFileKind -import io.github.miuzarte.scrcpyforandroid.services.RemoteFileStat +import io.github.miuzarte.scrcpyforandroid.services.* import io.github.miuzarte.scrcpyforandroid.storage.BundleSyncDelegate import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.flow.update +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext @@ -36,11 +23,11 @@ internal enum class FileManagerSortField { NAME, SIZE, TIME, EXTENSION } internal data class FileManagerScrollPosition(val index: Int, val offset: Int) internal sealed interface PendingTreeDownload { - data class File(val remotePath: String, val fileName: String) : PendingTreeDownload - data class Directory(val snapshot: DirectoryDownloadSnapshot) : PendingTreeDownload + data class File(val remotePath: String, val fileName: String): PendingTreeDownload + data class Directory(val snapshot: DirectoryDownloadSnapshot): PendingTreeDownload } -internal class FileManagerViewModel : ViewModel() { +internal class FileManagerViewModel: ViewModel() { private val asBundleSync = BundleSyncDelegate( sharedFlow = appSettings.bundleState, @@ -82,7 +69,7 @@ internal class FileManagerViewModel : ViewModel() { val sortField: StateFlow = asBundle .map { runCatching { FileManagerSortField.valueOf(it.fileManagerSortBy) }.getOrDefault( - FileManagerSortField.NAME + FileManagerSortField.NAME, ) } .stateIn( @@ -473,7 +460,7 @@ internal fun sortEntries( } return entries.sortedWith( compareByDescending { it.isDirectory } - .then(if (descending) comparator.reversed() else comparator) + .then(if (descending) comparator.reversed() else comparator), ) } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FullscreenControlScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FullscreenControlScreen.kt index aa14fbd..12bdfdc 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FullscreenControlScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/FullscreenControlScreen.kt @@ -10,29 +10,9 @@ import android.view.Surface import androidx.activity.compose.BackHandler import androidx.activity.compose.LocalActivity import androidx.compose.foundation.background -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.WindowInsets -import androidx.compose.foundation.layout.aspectRatio -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -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.mutableFloatStateOf -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset @@ -65,18 +45,8 @@ 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.util.Debouncer -import io.github.miuzarte.scrcpyforandroid.widgets.AppListBottomSheet -import io.github.miuzarte.scrcpyforandroid.widgets.AppListEntry -import io.github.miuzarte.scrcpyforandroid.widgets.ScrcpyVideoSurface -import io.github.miuzarte.scrcpyforandroid.widgets.VirtualButtonAction -import io.github.miuzarte.scrcpyforandroid.widgets.VirtualButtonActions -import io.github.miuzarte.scrcpyforandroid.widgets.VirtualButtonBar -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import io.github.miuzarte.scrcpyforandroid.widgets.* +import kotlinx.coroutines.* import top.yukonga.miuix.kmp.basic.Scaffold import top.yukonga.miuix.kmp.basic.SnackbarHost import top.yukonga.miuix.kmp.basic.Text @@ -126,7 +96,7 @@ fun FullscreenControlScreen( val buttonItems = remember(asBundle.virtualButtonsLayout) { VirtualButtonActions.splitLayout( - VirtualButtonActions.parseStoredLayout(asBundle.virtualButtonsLayout) + VirtualButtonActions.parseStoredLayout(asBundle.virtualButtonsLayout), ) } val floatingActions = remember(buttonItems) { @@ -137,7 +107,7 @@ fun FullscreenControlScreen( val fullscreenVirtualButtonHeight = asBundle.fullscreenVirtualButtonHeightDp.dp val fullscreenVirtualButtonDockSetting = remember(asBundle.fullscreenVirtualButtonDock) { AppSettings.FullscreenVirtualButtonDock.fromStoredValue( - asBundle.fullscreenVirtualButtonDock + asBundle.fullscreenVirtualButtonDock, ) } var displayRotation by remember(activity) { @@ -148,7 +118,7 @@ fun FullscreenControlScreen( if (displayManager == null || activity == null) { onDispose {} } else { - val listener = object : DisplayManager.DisplayListener { + val listener = object: DisplayManager.DisplayListener { override fun onDisplayAdded(displayId: Int) = Unit override fun onDisplayRemoved(displayId: Int) = Unit @@ -171,7 +141,8 @@ fun FullscreenControlScreen( AppSettings.FullscreenVirtualButtonDock.FOLLOW_TOP, AppSettings.FullscreenVirtualButtonDock.FOLLOW_BOTTOM, AppSettings.FullscreenVirtualButtonDock.FOLLOW_LEFT, - AppSettings.FullscreenVirtualButtonDock.FOLLOW_RIGHT -> null + AppSettings.FullscreenVirtualButtonDock.FOLLOW_RIGHT, + -> null AppSettings.FullscreenVirtualButtonDock.FIXED_TOP -> VirtualButtonBar.FullscreenDock.TOP AppSettings.FullscreenVirtualButtonDock.FIXED_BOTTOM -> VirtualButtonBar.FullscreenDock.BOTTOM @@ -250,7 +221,7 @@ fun FullscreenControlScreen( val restoreWindow = activity?.window if (restoreWindow != null) { WindowInsetsControllerCompat(restoreWindow, restoreWindow.decorView).show( - WindowInsetsCompat.Type.systemBars() + WindowInsetsCompat.Type.systemBars(), ) WindowCompat.setDecorFitsSystemWindows(restoreWindow, true) } @@ -320,7 +291,7 @@ fun FullscreenControlScreen( Log.w("FullscreenControlPage", "commitImeText failed", error) AppRuntime.snackbar( if (useClipboardPaste) R.string.fullscreen_paste_non_ascii - else R.string.fullscreen_text_input_failed + else R.string.fullscreen_text_input_failed, ) } } @@ -367,7 +338,7 @@ fun FullscreenControlScreen( Log.w("FullscreenControl", "pasteLocalClipboard failed", error) AppRuntime.snackbar( if (useLegacyPaste) R.string.fullscreen_legacy_paste_failed - else R.string.fullscreen_clipboard_sync_failed + else R.string.fullscreen_clipboard_sync_failed, ) } } @@ -383,7 +354,7 @@ fun FullscreenControlScreen( Log.w( "FullscreenControlPage", "sendKeycode failed for keycode=$it", - e + e, ) } } @@ -452,7 +423,7 @@ fun FullscreenControlScreen( VirtualButtonBar.FullscreenDock.BOTTOM -> Alignment.BottomCenter VirtualButtonBar.FullscreenDock.LEFT -> Alignment.CenterStart VirtualButtonBar.FullscreenDock.RIGHT -> Alignment.CenterEnd - } + }, ), dock = fullscreenVirtualButtonDock, reverseOrder = fullscreenVirtualButtonReverseOrder, @@ -582,10 +553,12 @@ private fun isFixedDockOrderReversed( ) return when (visualDock) { VirtualButtonBar.FullscreenDock.TOP, - VirtualButtonBar.FullscreenDock.BOTTOM -> visualDirection == DockDirection.RIGHT_TO_LEFT + VirtualButtonBar.FullscreenDock.BOTTOM, + -> visualDirection == DockDirection.RIGHT_TO_LEFT VirtualButtonBar.FullscreenDock.LEFT, - VirtualButtonBar.FullscreenDock.RIGHT -> visualDirection == DockDirection.BOTTOM_TO_TOP + VirtualButtonBar.FullscreenDock.RIGHT, + -> visualDirection == DockDirection.BOTTOM_TO_TOP } } @@ -707,7 +680,7 @@ fun FullscreenControlPage( Modifier.pointerInteropFilter { event -> touchEventHandler.handleMotionEvent(event) } - else Modifier + else Modifier, ) .onSizeChanged { size -> touchAreaSize = size @@ -736,7 +709,7 @@ fun FullscreenControlPage( else Modifier .fillMaxHeight() - .aspectRatio(sessionAspect) + .aspectRatio(sessionAspect), ), ) { ScrcpyVideoSurface( @@ -750,7 +723,7 @@ fun FullscreenControlPage( bounds.top.toInt(), bounds.right.toInt(), bounds.bottom.toInt(), - ) + ), ) }, session = session, @@ -779,7 +752,7 @@ fun FullscreenControlPage( .align(Alignment.TopStart) .padding(start = UiSpacing.ContentVertical, top = UiSpacing.ContentVertical) .background(Color.Black.copy(alpha = 0.5f)) - .padding(horizontal = UiSpacing.ContentVertical, vertical = UiSpacing.Medium) + .padding(horizontal = UiSpacing.ContentVertical, vertical = UiSpacing.Medium), ) { Column(verticalArrangement = Arrangement.spacedBy(UiSpacing.Tiny)) { Text( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/RecordPreferencesScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/RecordPreferencesScreen.kt index 03759ba..14f46ba 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/RecordPreferencesScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/RecordPreferencesScreen.kt @@ -1,28 +1,14 @@ package io.github.miuzarte.scrcpyforandroid.pages import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions 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 @@ -50,22 +36,8 @@ 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 -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.HorizontalDivider -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.SnackbarHost -import top.yukonga.miuix.kmp.basic.Text -import top.yukonga.miuix.kmp.basic.TextButton -import top.yukonga.miuix.kmp.basic.TextField -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.theme.MiuixTheme.colorScheme import top.yukonga.miuix.kmp.theme.MiuixTheme.textStyles @@ -168,7 +140,7 @@ private fun RecordPreferencesPage( TextFieldValue( text = soBundle.recordFilename, selection = TextRange(soBundle.recordFilename.length), - ) + ), ) } @@ -225,7 +197,7 @@ private fun RecordPreferencesPage( RecordFilenameTemplate.resolve( template = draftTemplate.text, sessionInfo = previewSessionInfo, - ) + ), ) } val listState = rememberSaveable( @@ -293,7 +265,7 @@ private fun RecordPreferencesPage( if (index > 0) HorizontalDivider() Column( modifier = Modifier.padding(horizontal = UiSpacing.Large), - verticalArrangement = Arrangement.spacedBy(UiSpacing.Small) + verticalArrangement = Arrangement.spacedBy(UiSpacing.Small), ) { Text( text = entry.value, @@ -302,7 +274,7 @@ private fun RecordPreferencesPage( ) Text( text = stringResource( - entry.descriptionResId ?: R.string.record_plain_text + entry.descriptionResId ?: R.string.record_plain_text, ), color = colorScheme.onSurfaceVariantSummary, fontSize = textStyles.body2.fontSize, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ReorderDevicesScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ReorderDevicesScreen.kt index abbad48..a155968 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ReorderDevicesScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/ReorderDevicesScreen.kt @@ -2,16 +2,8 @@ package io.github.miuzarte.scrcpyforandroid.pages import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height -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.res.stringResource import io.github.miuzarte.scrcpyforandroid.R @@ -20,11 +12,7 @@ import io.github.miuzarte.scrcpyforandroid.models.DeviceShortcuts import io.github.miuzarte.scrcpyforandroid.scaffolds.ReorderableList import io.github.miuzarte.scrcpyforandroid.storage.Settings import io.github.miuzarte.scrcpyforandroid.storage.Storage.quickDevices -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import kotlinx.coroutines.* import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet @Composable diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/StreamScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/StreamScreen.kt index 51c027d..4267a7a 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/StreamScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/StreamScreen.kt @@ -4,16 +4,7 @@ import android.content.pm.ActivityInfo import android.graphics.Rect import android.util.Rational import androidx.activity.compose.LocalActivity -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.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue +import androidx.compose.runtime.* import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.LocalLifecycleOwner diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalScreen.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalScreen.kt index e30586d..62a73fa 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalScreen.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalScreen.kt @@ -7,30 +7,12 @@ import android.view.KeyEvent import android.view.MotionEvent import android.view.ViewConfiguration import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.ime -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ContentCopy -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.mutableFloatStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -56,14 +38,7 @@ 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 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.IconButton -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.basic.TextField +import top.yukonga.miuix.kmp.basic.* import top.yukonga.miuix.kmp.blur.layerBackdrop import top.yukonga.miuix.kmp.icon.MiuixIcons import top.yukonga.miuix.kmp.icon.extended.More @@ -123,9 +98,9 @@ fun TerminalScreen( onClick = { output = "" }, - ) - ) - ) + ), + ), + ), ) { Icon( imageVector = MiuixIcons.More, @@ -140,7 +115,7 @@ fun TerminalScreen( Box( modifier = if (blurActive) Modifier.layerBackdrop(blurBackdrop) - else Modifier + else Modifier, ) { TerminalPage( viewModel = viewModel, @@ -298,7 +273,7 @@ private fun TerminalPage( } val terminalViewClient = remember { - object : TerminalViewClient { + object: TerminalViewClient { override fun onScale(scale: Float): Float { when { scale >= FONT_SCALE_STEP_THRESHOLD -> { @@ -360,7 +335,7 @@ private fun TerminalPage( terminalView?.setTerminalCursorBlinkerRate(500) terminalView?.setTerminalCursorBlinkerState( start = true, - startOnlyIfCursorEnabled = true + startOnlyIfCursorEnabled = true, ) viewModel.syncOutput { onOutputChange(it) } } @@ -419,7 +394,7 @@ private fun TerminalPage( // theme changes LaunchedEffect( colorScheme.surface, - colorScheme.onSurface + colorScheme.onSurface, ) { applyTheme() terminalView?.onScreenUpdated() @@ -546,7 +521,7 @@ private fun TerminalPage( TerminalExtraKeyButton( "CTRL", Modifier.weight(1f), - active = viewModel.ctrlLatched + active = viewModel.ctrlLatched, ) { haptic.contextClick() viewModel.ctrlLatched = !viewModel.ctrlLatched @@ -554,7 +529,7 @@ private fun TerminalPage( TerminalExtraKeyButton( "ALT", Modifier.weight(1f), - active = viewModel.altLatched + active = viewModel.altLatched, ) { haptic.contextClick() viewModel.altLatched = !viewModel.altLatched @@ -639,7 +614,7 @@ private fun TerminalOutputBottomSheet( LazyColumn( modifier = Modifier .fillMaxWidth() - .fillMaxHeight(2f / 3f) + .fillMaxHeight(2f / 3f), ) { item { TextField( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalViewModel.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalViewModel.kt index cf31a10..7eec434 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalViewModel.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/TerminalViewModel.kt @@ -16,15 +16,11 @@ import io.github.miuzarte.scrcpyforandroid.services.AppRuntime import io.github.miuzarte.scrcpyforandroid.services.LocalInputService import io.github.miuzarte.scrcpyforandroid.storage.BundleSyncDelegate import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings -import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext import top.yukonga.miuix.kmp.basic.SnackbarResult import java.nio.charset.StandardCharsets import kotlin.math.roundToInt @@ -32,7 +28,7 @@ import kotlin.math.roundToInt private const val DEFAULT_TERMINAL_FONT_SIZE_SP = 14f private const val LOG_TAG = "TerminalScreen" -internal class TerminalViewModel : ViewModel() { +internal class TerminalViewModel: ViewModel() { private val asBundleSync = BundleSyncDelegate( sharedFlow = appSettings.bundleState, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs2.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs2.kt index b5a43ab..5ea362f 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs2.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs2.kt @@ -20,7 +20,7 @@ private val OS2_PHONE_LIGHT = BgEffectConfig.Config( 0.95f, 0.14f, 0.27f, - 0.8f + 0.8f, ), colors1 = OS2_PHONE_LIGHT_COLORS, colors2 = OS2_PHONE_LIGHT_COLORS, @@ -51,7 +51,7 @@ private val OS2_PHONE_DARK = BgEffectConfig.Config( 0.81f, 0.14f, 0.24f, - 0.72f + 0.72f, ), colors1 = OS2_PHONE_DARK_COLORS, colors2 = OS2_PHONE_DARK_COLORS, @@ -82,7 +82,7 @@ private val OS2_PAD_LIGHT = BgEffectConfig.Config( 0.68f, 0.28f, 0.26f, - 0.62f + 0.62f, ), colors1 = OS2_PAD_LIGHT_COLORS, colors2 = OS2_PAD_LIGHT_COLORS, @@ -113,7 +113,7 @@ private val OS2_PAD_DARK = BgEffectConfig.Config( 0.71f, 0.43f, 0.09f, - 0.75f + 0.75f, ), colors1 = OS2_PAD_DARK_COLORS, colors2 = OS2_PAD_DARK_COLORS, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs3.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs3.kt index f8042e5..d2b889a 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs3.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/BgEffectConfigOs3.kt @@ -18,7 +18,7 @@ private val OS3_PHONE_LIGHT = BgEffectConfig.Config( 0.64f, 0.65f, 0.98f, - 1.0f + 1.0f, ), colors2 = floatArrayOf( 0.58f, @@ -36,7 +36,7 @@ private val OS3_PHONE_LIGHT = BgEffectConfig.Config( 0.97f, 0.77f, 0.84f, - 1.0f + 1.0f, ), colors3 = floatArrayOf( 0.98f, @@ -54,7 +54,7 @@ private val OS3_PHONE_LIGHT = BgEffectConfig.Config( 0.56f, 0.69f, 1.0f, - 1.0f + 1.0f, ), colorInterpPeriod = 5.0f, lightOffset = 0.1f, @@ -80,7 +80,7 @@ private val OS3_PHONE_DARK = BgEffectConfig.Config( 0.11f, 0.16f, 0.83f, - 0.4f + 0.4f, ), colors2 = floatArrayOf( 0.07f, @@ -98,7 +98,7 @@ private val OS3_PHONE_DARK = BgEffectConfig.Config( 0.0f, 0.2f, 0.78f, - 0.5f + 0.5f, ), colors3 = floatArrayOf( 0.58f, @@ -116,7 +116,7 @@ private val OS3_PHONE_DARK = BgEffectConfig.Config( 0.12f, 0.16f, 0.7f, - 0.6f + 0.6f, ), colorInterpPeriod = 8.0f, lightOffset = 0.0f, @@ -142,7 +142,7 @@ private val OS3_PAD_LIGHT = BgEffectConfig.Config( 0.98f, 0.76f, 0.8f, - 1.0f + 1.0f, ), colors2 = floatArrayOf( 0.66f, @@ -160,7 +160,7 @@ private val OS3_PAD_LIGHT = BgEffectConfig.Config( 0.97f, 0.77f, 0.84f, - 1.0f + 1.0f, ), colors3 = floatArrayOf( 0.97f, @@ -178,7 +178,7 @@ private val OS3_PAD_LIGHT = BgEffectConfig.Config( 0.72f, 0.73f, 0.98f, - 1.0f + 1.0f, ), colorInterpPeriod = 7.0f, lightOffset = 0.1f, @@ -204,7 +204,7 @@ private val OS3_PAD_DARK = BgEffectConfig.Config( 0.14f, 0.18f, 0.55f, - 0.5f + 0.5f, ), colors2 = floatArrayOf( 0.07f, @@ -222,7 +222,7 @@ private val OS3_PAD_DARK = BgEffectConfig.Config( 0.66f, 0.26f, 0.62f, - 0.5f + 0.5f, ), colors3 = floatArrayOf( 0.58f, @@ -240,7 +240,7 @@ private val OS3_PAD_DARK = BgEffectConfig.Config( 0.27f, 0.18f, 0.6f, - 0.6f + 0.6f, ), colorInterpPeriod = 7.0f, lightOffset = 0.0f, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/FrameTime.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/FrameTime.kt index 6c528e9..96c134c 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/FrameTime.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/pages/effect/FrameTime.kt @@ -1,12 +1,6 @@ package io.github.miuzarte.scrcpyforandroid.pages.effect -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.runtime.withFrameNanos +import androidx.compose.runtime.* @Composable internal fun rememberFrameTimeSeconds( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/BiometricGate.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/BiometricGate.kt index 868c606..e96be58 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/BiometricGate.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/BiometricGate.kt @@ -61,7 +61,7 @@ object BiometricGate { prompt = BiometricPrompt( activity, ContextCompat.getMainExecutor(activity), - object : BiometricPrompt.AuthenticationCallback() { + object: BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { finish(true) } @@ -71,7 +71,7 @@ object BiometricGate { } override fun onAuthenticationFailed() = Unit - } + }, ) prompt.authenticate( @@ -79,7 +79,7 @@ object BiometricGate { .setAllowedAuthenticators(ALLOWED_AUTHENTICATORS) .setTitle(title) .setSubtitle(subtitle) - .build() + .build(), ) continuation.invokeOnCancellation { diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordPickerPopup.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordPickerPopup.kt index 943f755..3f70eb8 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordPickerPopup.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordPickerPopup.kt @@ -6,11 +6,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Block import androidx.compose.material.icons.rounded.Password -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -20,12 +16,7 @@ import io.github.miuzarte.scrcpyforandroid.constants.UiSpacing import io.github.miuzarte.scrcpyforandroid.services.AppRuntime import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings 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.ListPopupColumn -import top.yukonga.miuix.kmp.basic.SpinnerItemImpl -import top.yukonga.miuix.kmp.basic.Text +import top.yukonga.miuix.kmp.basic.* import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme @Composable diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordRepository.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordRepository.kt index f610d33..502de03 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordRepository.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordRepository.kt @@ -22,7 +22,7 @@ object PasswordRepository { private const val PASSWORD_SUFFIX = ".password" private const val CREATED_WITH_AUTH_SUFFIX = ".created_with_auth" - class PasswordStorageCorruptedException(cause: Throwable) : Exception(cause) + class PasswordStorageCorruptedException(cause: Throwable): Exception(cause) private val _entriesState = MutableStateFlow>(emptyList()) val entriesState: StateFlow> = _entriesState.asStateFlow() @@ -191,7 +191,8 @@ object PasswordRepository { is PasswordStorageCorruptedException -> throwable.cause ?: throwable is KeyStoreException, is GeneralSecurityException, - is KeyPermanentlyInvalidatedException -> throwable + is KeyPermanentlyInvalidatedException, + -> throwable else -> throwable } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordUseCase.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordUseCase.kt index 9ee713c..f85b7d3 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordUseCase.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/password/PasswordUseCase.kt @@ -27,7 +27,7 @@ class PasswordUseCase { val password = entry.cipherText ?: return Result.failure( - IllegalStateException(AppRuntime.stringResource(R.string.password_expired)) + IllegalStateException(AppRuntime.stringResource(R.string.password_expired)), ) return Result.success(password.copyOf()) } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ArrowSlider.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ArrowSlider.kt index 80a8e17..00b927e 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ArrowSlider.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ArrowSlider.kt @@ -1,17 +1,9 @@ package io.github.miuzarte.scrcpyforandroid.scaffolds -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.* 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 diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt index 7869e52..a90c580 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/LazyColumn.kt @@ -1,15 +1,7 @@ package io.github.miuzarte.scrcpyforandroid.scaffolds 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.PaddingValues -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyListState @@ -60,7 +52,7 @@ fun LazyColumn( Modifier.pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() }) } - else Modifier + else Modifier, ), ) { val contentWidthModifier = @@ -78,7 +70,7 @@ fun LazyColumn( .then( if (scrollBehavior != null) Modifier.nestedScroll(scrollBehavior.nestedScrollConnection) - else Modifier + else Modifier, ), state = state, contentPadding = mergedContentPadding, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/OverlaySpinnerWithFallback.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/OverlaySpinnerWithFallback.kt index 8e55185..8b40bf9 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/OverlaySpinnerWithFallback.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/OverlaySpinnerWithFallback.kt @@ -9,11 +9,7 @@ import androidx.compose.ui.unit.Dp import io.github.miuzarte.scrcpyforandroid.R import io.github.miuzarte.scrcpyforandroid.miuix.OverlaySpinnerPreference import io.github.miuzarte.scrcpyforandroid.miuix.SpinnerEntry -import top.yukonga.miuix.kmp.basic.BasicComponentColors -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.* /** * [OverlaySpinnerPreference] wrapper with fallback value display and loading state. @@ -57,7 +53,7 @@ fun OverlaySpinnerWithFallback( SpinnerEntry( title = overrideEndActionValue, enabled = true, // 保持启用以显示蓝色而非灰色 - ) + ), ) } if (dataLoading) { @@ -66,7 +62,7 @@ fun OverlaySpinnerWithFallback( icon = { mod -> InfiniteProgressIndicator(mod) }, title = textLoading, enabled = false, - ) + ), ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ReorderableList.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ReorderableList.kt index cd27e72..7d3e147 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ReorderableList.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/ReorderableList.kt @@ -1,15 +1,7 @@ package io.github.miuzarte.scrcpyforandroid.scaffolds import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -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.material.icons.Icons import androidx.compose.material.icons.rounded.DragIndicator import androidx.compose.material3.IconButton @@ -51,13 +43,13 @@ class ReorderableList( val icon: ImageVector, val contentDescription: String, val onClick: () -> Unit, - ) : EndAction + ): EndAction data class Checkbox( val checked: Boolean, val enabled: Boolean = true, val onClick: () -> Unit, - ) : EndAction + ): EndAction } data class Item( @@ -94,7 +86,7 @@ class ReorderableList( .height(IntrinsicSize.Min) .padding( horizontal = UiSpacing.CardTitle, - vertical = UiSpacing.FieldLabelBottom + vertical = UiSpacing.FieldLabelBottom, ), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, @@ -108,14 +100,14 @@ class ReorderableList( Modifier.clickable(onClick = item.onClick) } else { Modifier - } + }, ), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(UiSpacing.Small) + horizontalArrangement = Arrangement.spacedBy(UiSpacing.Small), ) { if (item.icon != null) Icon( item.icon, - contentDescription = item.title + contentDescription = item.title, ) Column { Text( @@ -132,7 +124,7 @@ class ReorderableList( } Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(UiSpacing.Small) + horizontalArrangement = Arrangement.spacedBy(UiSpacing.Small), ) { item.endActions.forEach { action -> EndActionView( @@ -181,7 +173,7 @@ class ReorderableList( modifier = Modifier .padding( horizontal = UiSpacing.CardTitle, - vertical = UiSpacing.FieldLabelBottom + vertical = UiSpacing.FieldLabelBottom, ), horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -191,7 +183,7 @@ class ReorderableList( Modifier.clickable(onClick = item.onClick) } else { Modifier - } + }, ), verticalAlignment = Alignment.CenterVertically, ) { diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperTextField.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperTextField.kt index d3f000f..83be2ef 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperTextField.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scaffolds/SuperTextField.kt @@ -3,18 +3,12 @@ package io.github.miuzarte.scrcpyforandroid.scaffolds import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue +import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.VisualTransformation diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ClientOptions.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ClientOptions.kt index 78c0f4b..e26627c 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ClientOptions.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ClientOptions.kt @@ -1,15 +1,6 @@ package io.github.miuzarte.scrcpyforandroid.scrcpy -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.AudioSource -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.CameraFacing -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Codec -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.DisplayImePolicy -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.ListOptions -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.LogLevel -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Orientation -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.OrientationLock -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Tick -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.VideoSource +import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.* import io.github.miuzarte.scrcpyforandroid.services.NativeRecordingSupport data class ClientOptions( @@ -304,7 +295,7 @@ data class ClientOptions( if (!video && !audio && !control) { throw IllegalArgumentException( - "nothing to do" + "nothing to do", ) } @@ -315,13 +306,13 @@ data class ClientOptions( if (newDisplay.isNotBlank()) { if (videoSource != VideoSource.DISPLAY) { throw IllegalArgumentException( - "--new-display is only available with --video-source=display" + "--new-display is only available with --video-source=display", ) } if (!video) { throw IllegalArgumentException( - "--new-display is incompatible with --no-video" + "--new-display is incompatible with --no-video", ) } } @@ -329,39 +320,39 @@ data class ClientOptions( if (videoSource == VideoSource.CAMERA) { if (displayId > 0) { throw IllegalArgumentException( - "--display-id is only available with --video-source=display" + "--display-id is only available with --video-source=display", ) } if (displayImePolicy != DisplayImePolicy.UNDEFINED) { throw IllegalArgumentException( - "--display-ime-policy is only available with --video-source=display" + "--display-ime-policy is only available with --video-source=display", ) } if (cameraId.isNotBlank() && cameraFacing != CameraFacing.ANY) { throw IllegalArgumentException( - "Cannot specify both --camera-id and --camera-facing" + "Cannot specify both --camera-id and --camera-facing", ) } if (cameraSize.isNotBlank()) { if (maxSize > 0u) { throw IllegalArgumentException( - "Cannot specify both --camera-size and -m/--max-size" + "Cannot specify both --camera-size and -m/--max-size", ) } if (cameraAr.isNotBlank()) { throw IllegalArgumentException( - "--camera-high-speed requires an explicit --camera-fps value" + "--camera-high-speed requires an explicit --camera-fps value", ) } } if (cameraHighSpeed && cameraFps <= 0u) { throw IllegalArgumentException( - "--camera-high-speed requires an explicit --camera-fps value" + "--camera-high-speed requires an explicit --camera-fps value", ) } @@ -376,13 +367,13 @@ data class ClientOptions( || cameraSize.isNotBlank() ) { throw IllegalArgumentException( - "Camera options are only available with --video-source=camera" + "Camera options are only available with --video-source=camera", ) } if (displayId > 0 && newDisplay.isNotBlank()) { throw IllegalArgumentException( - "Cannot specify both --display-id and --new-display" + "Cannot specify both --display-id and --new-display", ) } @@ -390,19 +381,19 @@ data class ClientOptions( if (videoSource != VideoSource.DISPLAY || newDisplay.isBlank()) { throw IllegalArgumentException( "-x/--flex-display can only be applied to displays created " + - "with --new-display" + "with --new-display", ) } if (!control) { throw IllegalArgumentException( - "-n/--no-control is not compatible with -x/--flex-display" + "-n/--no-control is not compatible with -x/--flex-display", ) } if (crop.isNotBlank()) { throw IllegalArgumentException( - "--crop is not compatible with -x/--flex-display" + "--crop is not compatible with -x/--flex-display", ) } } @@ -411,7 +402,7 @@ data class ClientOptions( && displayId == 0 && newDisplay.isBlank() ) { throw IllegalArgumentException( - "--display-ime-policy is only supported on a secondary display" + "--display-ime-policy is only supported on a secondary display", ) } @@ -432,27 +423,27 @@ data class ClientOptions( if (audioDup) { if (!audio) { throw IllegalArgumentException( - "--audio-dup not supported if audio is disabled" + "--audio-dup not supported if audio is disabled", ) } if (audioSource != AudioSource.PLAYBACK) { throw IllegalArgumentException( - "--audio-dup is specific to --audio-source=playback" + "--audio-dup is specific to --audio-source=playback", ) } } if (recordFormat != RecordFormat.AUTO && recordFilename.isBlank()) { throw IllegalArgumentException( - "Record format specified without recording" + "Record format specified without recording", ) } if (recordFilename.isNotBlank()) { if (!video && !audio) { throw IllegalArgumentException( - "Video and audio disabled, nothing to record" + "Video and audio disabled, nothing to record", ) } @@ -461,14 +452,14 @@ data class ClientOptions( if (recordFormat == RecordFormat.AUTO) { throw IllegalArgumentException( "No format specified for recording file " + - "(try with --record-format=mp4)" + "(try with --record-format=mp4)", ) } } if (!NativeRecordingSupport.isSupported(recordFormat)) { throw IllegalArgumentException( - "Android native recording currently supports only MP4/M4A" + "Android native recording currently supports only MP4/M4A", ) } @@ -476,14 +467,14 @@ data class ClientOptions( if (recordOrientation.isMirror()) { throw IllegalArgumentException( "Record orientation only supports rotation, " + - "not flipping: ${recordOrientation.string}" + "not flipping: ${recordOrientation.string}", ) } } if (video && recordFormat.isAudioOnly()) { throw IllegalArgumentException( - "Audio container does not support video stream" + "Audio container does not support video stream", ) } @@ -554,32 +545,32 @@ data class ClientOptions( if (!control) { if (turnScreenOff) { throw IllegalArgumentException( - "Cannot request to turn screen off if control is disabled" + "Cannot request to turn screen off if control is disabled", ) } if (stayAwake) { throw IllegalArgumentException( - "Cannot request to stay awake if control is disabled" + "Cannot request to stay awake if control is disabled", ) } if (showTouches) { throw IllegalArgumentException( - "Cannot request to show touches if control is disabled" + "Cannot request to show touches if control is disabled", ) } if (powerOffOnClose) { throw IllegalArgumentException( - "Cannot request power off on close if control is disabled" + "Cannot request power off on close if control is disabled", ) } if (startApp.isNotBlank()) { throw IllegalArgumentException( - "Cannot start an Android app if control is disabled" + "Cannot start an Android app if control is disabled", ) } if (keepActive) { throw IllegalArgumentException( - "Cannot keep device active if control is disabled" + "Cannot keep device active if control is disabled", ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/Scrcpy.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/Scrcpy.kt index 53daf84..d0665bb 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/Scrcpy.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/Scrcpy.kt @@ -12,36 +12,18 @@ import io.github.miuzarte.scrcpyforandroid.constants.Defaults import io.github.miuzarte.scrcpyforandroid.nativecore.AdbSocketStream import io.github.miuzarte.scrcpyforandroid.nativecore.NativeAdbService import io.github.miuzarte.scrcpyforandroid.nativecore.ScrcpyAudioPlayer -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.CameraFacing -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Codec -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.EncoderType -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.ListOptions -import io.github.miuzarte.scrcpyforandroid.services.AppRuntime +import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.* +import io.github.miuzarte.scrcpyforandroid.services.* import io.github.miuzarte.scrcpyforandroid.services.EventLogger.logEvent -import io.github.miuzarte.scrcpyforandroid.services.LocalInputService -import io.github.miuzarte.scrcpyforandroid.services.NativeAacRecorder -import io.github.miuzarte.scrcpyforandroid.services.NativeMp4Recorder -import io.github.miuzarte.scrcpyforandroid.services.NativeWavRecorder -import io.github.miuzarte.scrcpyforandroid.services.RecordingFileResolver import io.github.miuzarte.scrcpyforandroid.storage.Storage.appSettings -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withContext -import java.io.BufferedInputStream -import java.io.BufferedReader -import java.io.DataInputStream -import java.io.DataOutputStream -import java.io.EOFException -import java.io.File -import java.io.InputStreamReader +import java.io.* import java.nio.ByteBuffer import java.nio.ByteOrder import java.util.ArrayDeque @@ -228,7 +210,7 @@ class Scrcpy( TAG, "start(): create audio player codecId=0x${ info.audioCodecId.toUInt().toString(16) - }" + }", ) val player = ScrcpyAudioPlayer(appContext, info.audioCodecId, lowLatency) audioPlayer = player @@ -243,7 +225,8 @@ class Scrcpy( val recordFile = RecordingFileResolver.resolve(options, info) when (options.recordFormat) { ClientOptions.RecordFormat.MP4, - ClientOptions.RecordFormat.M4A -> { + ClientOptions.RecordFormat.M4A, + -> { val recorder = NativeMp4Recorder( outputFile = recordFile, includeVideo = options.video, @@ -296,13 +279,16 @@ class Scrcpy( } Log.i( - TAG, "start(): Session started successfully - device=${info.deviceName}, " + - "video=${if (options.video) buildString { - append(info.codec?.string ?: "null") - if (info.width > 0 && info.height > 0) append(" ${info.width}x${info.height}") - } else "off"}, " + + TAG, + "start(): Session started successfully - device=${info.deviceName}, " + + "video=${ + if (options.video) buildString { + append(info.codec?.string ?: "null") + if (info.width > 0 && info.height > 0) append(" ${info.width}x${info.height}") + } else "off" + }, " + "audio=${if (options.audio) options.audioCodec.string else "off"}, " + - "control=${options.control}" + "control=${options.control}", ) return@withContext info @@ -637,9 +623,11 @@ class Scrcpy( runTrackedFetch { val output = executeList(ListOptions.CAMERA_SIZES) val parsed = parseCameraSizes(output) - .sortedWith(compareByDescending { size -> - size.substringBefore('x').toIntOrNull() ?: 0 - }) + .sortedWith( + compareByDescending { size -> + size.substringBefore('x').toIntOrNull() ?: 0 + }, + ) cachedCameraSizes = parsed logListPreview( list = ListOptions.CAMERA_SIZES, @@ -789,7 +777,7 @@ class Scrcpy( id = match.groupValues[1].toInt(), width = match.groupValues[2].toInt(), height = match.groupValues[3].toInt(), - ) + ), ) } return displays.toList() @@ -810,7 +798,7 @@ class Scrcpy( facing = CameraFacing.fromString(facing), activeSize = activeSize, fps = fpsValues.map(Int::toUShort), - ) + ), ) } return cameras.toList() @@ -832,7 +820,7 @@ class Scrcpy( system = match.groupValues[1] == "*", label = match.groupValues[2].trim(), packageName = match.groupValues[3].trim(), - ) + ), ) } return apps.toList().sortedBy { appSortKey(it) } @@ -1079,7 +1067,7 @@ class Scrcpy( Log.w(TAG, "audio disabled by server") if (options.requireAudio) { throw IllegalStateException( - "Audio is required but was disabled by the server" + "Audio is required but was disabled by the server", ) } 0 @@ -1089,7 +1077,7 @@ class Scrcpy( Log.e(TAG, "audio stream configuration error from server") if (options.requireAudio) { throw IllegalStateException( - "Audio is required but the server failed to configure audio capture" + "Audio is required but the server failed to configure audio capture", ) } 0 @@ -1098,7 +1086,7 @@ class Scrcpy( else -> { Log.i( TAG, - "audio stream codec=0x${streamCodecId.toUInt().toString(16)}" + "audio stream codec=0x${streamCodecId.toUInt().toString(16)}", ) streamCodecId } @@ -1191,7 +1179,7 @@ class Scrcpy( (headerBuf[11].toInt() and 0xFF) Log.i( TAG, - "video session packet: ${sw}x${sh} clientResized=$clientResized" + "video session packet: ${sw}x${sh} clientResized=$clientResized", ) onVideoSessionSize(sw, sh) continue @@ -1261,7 +1249,7 @@ class Scrcpy( val packet = AudioPacket( data = payload, ptsUs = ptsUs, - isConfig = isConfig + isConfig = isConfig, ) audioConsumers.forEach { it(packet) } } catch (_: EOFException) { @@ -1349,7 +1337,7 @@ class Scrcpy( screenHeight, pressure, actionButton, - buttons + buttons, ) } catch (e: IllegalStateException) { Log.w(TAG, "injectTouch(): control channel not available", e) @@ -1373,7 +1361,7 @@ class Scrcpy( screenHeight, hScroll, vScroll, - buttons + buttons, ) } catch (e: IllegalStateException) { Log.w(TAG, "injectScroll(): control channel not available", e) @@ -1496,15 +1484,15 @@ class Scrcpy( private fun startServerLogThread( serverStream: AdbSocketStream, - socketName: String + socketName: String, ): Thread { return thread(start = true, name = "scrcpy-server-log") { try { BufferedReader( InputStreamReader( serverStream.inputStream, - Charsets.UTF_8 - ) + Charsets.UTF_8, + ), ).use { reader -> while (true) { val line = reader.readLine() ?: break @@ -1539,7 +1527,7 @@ class Scrcpy( private suspend fun openAbstractSocketWithRetry( socketName: String, - expectDummyByte: Boolean + expectDummyByte: Boolean, ): AdbSocketStream { var lastEx: Exception? = null repeat(CONNECT_RETRY_COUNT) { attempt -> @@ -1713,7 +1701,7 @@ class Scrcpy( screenHeight: Int, hScroll: Float, vScroll: Float, - buttons: Int + buttons: Int, ) { output.writeByte(TYPE_INJECT_SCROLL_EVENT) writePosition(x, y, screenWidth, screenHeight) diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ServerParams.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ServerParams.kt index f9897b5..93154d1 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ServerParams.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/ServerParams.kt @@ -1,15 +1,6 @@ package io.github.miuzarte.scrcpyforandroid.scrcpy -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.AudioSource -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.CameraFacing -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Codec -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.DisplayImePolicy -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.ListOptions -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.LogLevel -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Orientation -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.OrientationLock -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Tick -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.VideoSource +import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.* // 启动 scrcpy 前直接继承自 [ClientOptions], // 不需要默认值 diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/TouchEventHandler.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/TouchEventHandler.kt index 6c4e945..dda4ce1 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/TouchEventHandler.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/scrcpy/TouchEventHandler.kt @@ -186,7 +186,8 @@ class TouchEventHandler( val isHoverMotion = when (event.actionMasked) { MotionEvent.ACTION_HOVER_ENTER, MotionEvent.ACTION_HOVER_MOVE, - MotionEvent.ACTION_HOVER_EXIT -> true + MotionEvent.ACTION_HOVER_EXIT, + -> true MotionEvent.ACTION_MOVE -> buttons == 0 else -> false @@ -201,7 +202,8 @@ class TouchEventHandler( ) { when (event.actionMasked) { MotionEvent.ACTION_DOWN, - MotionEvent.ACTION_BUTTON_PRESS -> { + MotionEvent.ACTION_BUTTON_PRESS, + -> { coroutineScope.launch { runCatching { onBackOrScreenOn(0) @@ -212,7 +214,8 @@ class TouchEventHandler( } MotionEvent.ACTION_UP, - MotionEvent.ACTION_BUTTON_RELEASE -> { + MotionEvent.ACTION_BUTTON_RELEASE, + -> { coroutineScope.launch { runCatching { onBackOrScreenOn(1) @@ -234,7 +237,8 @@ class TouchEventHandler( MotionEvent.ACTION_MOVE -> MotionEvent.ACTION_MOVE MotionEvent.ACTION_BUTTON_PRESS, - MotionEvent.ACTION_BUTTON_RELEASE -> return true + MotionEvent.ACTION_BUTTON_RELEASE, + -> return true else -> return true } @@ -343,7 +347,7 @@ class TouchEventHandler( Log.w( FULLSCREEN_TOUCH_LOG_TAG, "handlePointerDown failed for pointerId=$pointerId", - e + e, ) } } @@ -373,7 +377,7 @@ class TouchEventHandler( Log.w( FULLSCREEN_TOUCH_LOG_TAG, "handlePointerMove failed for pointerId=$pointerId", - e + e, ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppRuntime.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppRuntime.kt index d5749af..86bc06d 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppRuntime.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppRuntime.kt @@ -2,7 +2,6 @@ package io.github.miuzarte.scrcpyforandroid.services import android.content.Context import androidx.annotation.StringRes -import io.github.miuzarte.scrcpyforandroid.R import io.github.miuzarte.scrcpyforandroid.models.ConnectionTarget import io.github.miuzarte.scrcpyforandroid.nativecore.AdbMdnsDiscoverer import io.github.miuzarte.scrcpyforandroid.scrcpy.Scrcpy diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppUpdateChecker.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppUpdateChecker.kt index e2606bc..0f59912 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppUpdateChecker.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/AppUpdateChecker.kt @@ -32,10 +32,10 @@ object AppUpdateChecker { ) sealed interface State { - data object Idle : State - data object Checking : State - data object Error : State - data class Ready(val release: ReleaseInfo) : State + data object Idle: State + data object Checking: State + data object Error: State + data class Ready(val release: ReleaseInfo): State } private val checkMutex = Mutex() diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbAutoReconnectManager.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbAutoReconnectManager.kt index b01a8b8..ce9077f 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbAutoReconnectManager.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbAutoReconnectManager.kt @@ -7,7 +7,7 @@ internal class DeviceAdbAutoReconnectManager( private val controller: ConnectionController, private val stateStore: ConnectionStateStore, private val backgroundRunner: DeviceAdbBackgroundRunner = DeviceAdbBackgroundRunner(), -) : Closeable { +): Closeable { suspend fun runKeepAliveLoop( isForeground: () -> Boolean, intervalMs: Long, @@ -31,7 +31,7 @@ internal class DeviceAdbAutoReconnectManager( onReconnectFailure = onReconnectFailure, shouldAutoReconnect = { stateStore.state.value.disconnectCause != DisconnectCause.User && - stateStore.state.value.disconnectCause != DisconnectCause.KillAdbOnClose + stateStore.state.value.disconnectCause != DisconnectCause.KillAdbOnClose }, ) } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbBackgroundRunner.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbBackgroundRunner.kt index a8ea1d6..21f12f2 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbBackgroundRunner.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbBackgroundRunner.kt @@ -1,15 +1,11 @@ package io.github.miuzarte.scrcpyforandroid.services import io.github.miuzarte.scrcpyforandroid.models.DeviceShortcut -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExecutorCoroutineDispatcher -import kotlinx.coroutines.asCoroutineDispatcher -import kotlinx.coroutines.delay -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import java.io.Closeable import java.util.concurrent.Executors -internal class DeviceAdbBackgroundRunner : Closeable { +internal class DeviceAdbBackgroundRunner: Closeable { private val executor = Executors.newSingleThreadExecutor { runnable -> Thread(runnable, "device-adb-monitor").apply { isDaemon = true } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbConnectionCoordinator.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbConnectionCoordinator.kt index 70c541a..1e1881d 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbConnectionCoordinator.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceAdbConnectionCoordinator.kt @@ -22,7 +22,7 @@ internal data class DeviceAdbSessionState( val connectedScrcpyProfileId: String = ScrcpyOptions.GLOBAL_PROFILE_ID, val audioForwardingSupported: Boolean = true, val cameraMirroringSupported: Boolean = true, -) : Parcelable +): Parcelable internal class DeviceAdbConnectionCoordinator( private val adbService: NativeAdbService = NativeAdbService, diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceConnectionLogic.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceConnectionLogic.kt index 2cab3f9..604e6b7 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceConnectionLogic.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/DeviceConnectionLogic.kt @@ -25,7 +25,7 @@ data class ConnectedDeviceInfo( internal suspend fun fetchConnectedDeviceInfo( adbService: NativeAdbService, host: String, - port: Int + port: Int, ): ConnectedDeviceInfo = withContext(Dispatchers.IO) { val values = runCatching { adbService.shellBatch { diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt index 190390d..47fd32f 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/EventLogger.kt @@ -10,11 +10,11 @@ import java.util.Date import java.util.Locale sealed interface EventLogMessage { - data class Raw(val text: String) : EventLogMessage + data class Raw(val text: String): EventLogMessage data class Resource( @param:StringRes val resId: Int, val args: List = emptyList(), - ) : EventLogMessage + ): EventLogMessage } data class EventLogEntry( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/FileManagerService.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/FileManagerService.kt index 6e83fd8..8f4bcea 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/FileManagerService.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/FileManagerService.kt @@ -86,7 +86,7 @@ object FileManagerService { private val listTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm") private val displayTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss") private val listLineRegex = Regex( - """^\s*(\d+)\s+([\-bcdlps][rwxstST-]{9})\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})\s+(.+)$""" + """^\s*(\d+)\s+([\-bcdlps][rwxstST-]{9})\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})\s+(.+)$""", ) private val sizeFormatter = DecimalFormat("0.00") @@ -101,7 +101,7 @@ object FileManagerService { .filterNot { it.name == "." || it.name == ".." } .sortedWith( compareByDescending { it.isDirectory } - .thenBy { it.name.lowercase() } + .thenBy { it.name.lowercase() }, ) .toList() } @@ -173,7 +173,7 @@ object FileManagerService { targetFile.outputStream().use { output -> NativeAdbService.pull( joinRemotePath(snapshot.remoteRootPath, relativePath), - output + output, ) } } @@ -189,7 +189,7 @@ object FileManagerService { NativeAdbService.ensureConnectionResponsive() val rootDocument = DocumentsContract.buildDocumentUriUsingTree( treeUri, - DocumentsContract.getTreeDocumentId(treeUri) + DocumentsContract.getTreeDocumentId(treeUri), ) val target = createUniqueDocument(context, rootDocument, fileName, guessMimeType(fileName)) context.contentResolver.openOutputStream(target, "w").use { output -> @@ -206,7 +206,7 @@ object FileManagerService { NativeAdbService.ensureConnectionResponsive() val rootDocument = DocumentsContract.buildDocumentUriUsingTree( treeUri, - DocumentsContract.getTreeDocumentId(treeUri) + DocumentsContract.getTreeDocumentId(treeUri), ) val folderName = snapshot.remoteRootPath.substringAfterLast('/').ifBlank { "Scrcpy" } val folderRoot = createUniqueDirectoryDocument(context, rootDocument, folderName) @@ -327,7 +327,7 @@ object FileManagerService { val dateTime = runCatching { LocalDateTime.parse( "${match.groupValues[7]} ${match.groupValues[8]}", - listTimeFormatter + listTimeFormatter, ) }.getOrNull() val nameField = match.groupValues[9] @@ -542,7 +542,7 @@ object FileManagerService { private fun createUniqueDirectoryDocument( context: Context, parentDocument: Uri, - baseName: String + baseName: String, ): Uri { var name = baseName var index = 1 @@ -551,7 +551,7 @@ object FileManagerService { context, parentDocument, name, - DocumentsContract.Document.MIME_TYPE_DIR + DocumentsContract.Document.MIME_TYPE_DIR, ) != null ) { name = "$baseName ($index)" @@ -592,7 +592,7 @@ object FileManagerService { private fun ensureTreeDirectory( context: Context, rootDocument: Uri, - relativePath: String + relativePath: String, ): Uri { var current = rootDocument if (relativePath.isBlank()) return current @@ -603,14 +603,15 @@ object FileManagerService { context, current, segment, - DocumentsContract.Document.MIME_TYPE_DIR + DocumentsContract.Document.MIME_TYPE_DIR, ) current = existing ?: DocumentsContract.createDocument( context.contentResolver, current, DocumentsContract.Document.MIME_TYPE_DIR, segment, - ) ?: throw IOException("${AppRuntime.stringResource(R.string.fm_exception_cannot_create_dir)}: $segment") + ) + ?: throw IOException("${AppRuntime.stringResource(R.string.fm_exception_cannot_create_dir)}: $segment") } return current } @@ -653,15 +654,15 @@ object FileManagerService { class DirectorySnapshotSession private constructor( private val shellSession: InteractiveShellSession, -) : Closeable { +): Closeable { suspend fun load(path: String): DirectoryDownloadSnapshot { val normalizedPath = path.trimEnd('/').ifBlank { "/" } val totalBytes = parseDuBytes( - shellSession.execute("du -sb ${FileManagerService.quoteShellArg(normalizedPath)}") + shellSession.execute("du -sb ${FileManagerService.quoteShellArg(normalizedPath)}"), ) val directories = shellSession.execute( - "find ${FileManagerService.quoteShellArg(normalizedPath)} -type d" + "find ${FileManagerService.quoteShellArg(normalizedPath)} -type d", ) .lineSequence() .map(String::trim) @@ -671,7 +672,7 @@ class DirectorySnapshotSession private constructor( .toList() val files = shellSession.execute( - "find ${FileManagerService.quoteShellArg(normalizedPath)} -type f" + "find ${FileManagerService.quoteShellArg(normalizedPath)} -type f", ) .lineSequence() .map(String::trim) @@ -723,7 +724,7 @@ class DirectorySnapshotSession private constructor( private class InteractiveShellSession private constructor( private val stream: AdbSocketStream, -) : Closeable { +): Closeable { private val mutex = Mutex() suspend fun execute(command: String): String = withContext(Dispatchers.IO) { diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PictureInPictureActionReceiver.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PictureInPictureActionReceiver.kt index 58c01e5..3cff102 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PictureInPictureActionReceiver.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PictureInPictureActionReceiver.kt @@ -9,7 +9,7 @@ import io.github.miuzarte.scrcpyforandroid.BuildConfig import kotlinx.coroutines.runBlocking // not working in MIUI -class PictureInPictureActionReceiver : BroadcastReceiver() { +class PictureInPictureActionReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent?) { if (intent?.action != ACTION_STOP_SCRCPY) return val pendingResult = goAsync() diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PublicDirs.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PublicDirs.kt index 3675f84..662fc57 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PublicDirs.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/services/PublicDirs.kt @@ -9,14 +9,14 @@ object PublicDirs { fun transferDirectory(): File { return File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), - ROOT_DIRECTORY + ROOT_DIRECTORY, ) } fun recordDirectory(): File { return File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), - ROOT_DIRECTORY + ROOT_DIRECTORY, ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AdbClientData.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AdbClientData.kt index 0314285..b937e41 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AdbClientData.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AdbClientData.kt @@ -7,7 +7,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey import kotlinx.coroutines.flow.StateFlow import kotlinx.parcelize.Parcelize -class AdbClientData(context: Context) : Settings(context, "AdbClient") { +class AdbClientData(context: Context): Settings(context, "AdbClient") { companion object { val RSA_PRIVATE_KEY = Pair( stringPreferencesKey("rsa_private_key"), @@ -50,7 +50,7 @@ class AdbClientData(context: Context) : Settings(context, "AdbClient") { val importedPrivateKeyFileName: String, val importedPublicKeyX509: String, val importedPublicKeyFileName: String, - ) : Parcelable { + ): Parcelable { } private val bundleFields = arrayOf>( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt index 99f571b..9a3068b 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/AppSettings.kt @@ -3,19 +3,14 @@ package io.github.miuzarte.scrcpyforandroid.storage import android.content.Context import android.os.Parcelable import androidx.annotation.StringRes -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.booleanPreferencesKey -import androidx.datastore.preferences.core.floatPreferencesKey -import androidx.datastore.preferences.core.intPreferencesKey -import androidx.datastore.preferences.core.longPreferencesKey -import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.core.* import io.github.miuzarte.scrcpyforandroid.R import io.github.miuzarte.scrcpyforandroid.scrcpy.Scrcpy import kotlinx.coroutines.flow.StateFlow import kotlinx.parcelize.Parcelize import top.yukonga.miuix.kmp.theme.ColorSchemeMode -class AppSettings(context: Context) : Settings(context, "AppSettings") { +class AppSettings(context: Context): Settings(context, "AppSettings") { object ThemeModes { data class Option( @field:StringRes val labelResId: Int, @@ -92,6 +87,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { stringPreferencesKey("language_tag"), "", ) + // Theme val THEME_BASE_INDEX = Pair( intPreferencesKey("theme_base_index"), @@ -360,7 +356,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") { val lastUpdateCheckAt: Long, val clearLogsOnExit: Boolean, val hideDeviceLogs: Boolean, - ) : Parcelable { + ): Parcelable { } private val bundleFields = arrayOf>( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/BundleSync.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/BundleSync.kt index 65cfe88..fe6f77f 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/BundleSync.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/BundleSync.kt @@ -1,29 +1,9 @@ package io.github.miuzarte.scrcpyforandroid.storage -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.MutableState -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 kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* /** * Manages a local copy of a bundle from persistent storage with debounced save. diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/QuickDevices.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/QuickDevices.kt index ccd05a2..9182130 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/QuickDevices.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/QuickDevices.kt @@ -7,7 +7,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey import kotlinx.coroutines.flow.StateFlow import kotlinx.parcelize.Parcelize -class QuickDevices(context: Context) : Settings(context, "QuickDevices") { +class QuickDevices(context: Context): Settings(context, "QuickDevices") { companion object { val QUICK_DEVICES_LIST = Pair( stringPreferencesKey("quick_devices_list"), @@ -26,7 +26,7 @@ class QuickDevices(context: Context) : Settings(context, "QuickDevices") { data class Bundle( val quickDevicesList: String, val quickConnectInput: String, - ) : Parcelable { + ): Parcelable { } private val bundleFields = arrayOf>( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyOptions.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyOptions.kt index fbc6f1f..8c8d8d1 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyOptions.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyOptions.kt @@ -2,31 +2,18 @@ package io.github.miuzarte.scrcpyforandroid.storage import android.content.Context import android.os.Parcelable -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.booleanPreferencesKey -import androidx.datastore.preferences.core.intPreferencesKey -import androidx.datastore.preferences.core.longPreferencesKey -import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.core.* import io.github.miuzarte.scrcpyforandroid.R import io.github.miuzarte.scrcpyforandroid.scrcpy.ClientOptions import io.github.miuzarte.scrcpyforandroid.scrcpy.ClientOptions.KeyInjectMode import io.github.miuzarte.scrcpyforandroid.scrcpy.ClientOptions.RecordFormat -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.AudioSource -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.CameraFacing -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Codec -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.DisplayImePolicy -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.ListOptions -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.LogLevel -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Orientation -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.OrientationLock -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.Tick -import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.VideoSource +import io.github.miuzarte.scrcpyforandroid.scrcpy.Shared.* import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.runBlocking import kotlinx.parcelize.Parcelize import org.json.JSONObject -class ScrcpyOptions(context: Context) : Settings(context, "ScrcpyOptions") { +class ScrcpyOptions(context: Context): Settings(context, "ScrcpyOptions") { companion object { const val GLOBAL_PROFILE_ID = "global" val GLOBAL_PROFILE_NAME_RES_ID = R.string.text_global @@ -435,7 +422,7 @@ class ScrcpyOptions(context: Context) : Settings(context, "ScrcpyOptions") { val cameraTorch: Boolean, val keepActive: Boolean, val flexDisplay: Boolean, - ) : Parcelable { + ): Parcelable { } private val bundleFields = arrayOf>( diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyProfiles.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyProfiles.kt index 50dcbe3..09a7f7e 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyProfiles.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/ScrcpyProfiles.kt @@ -8,7 +8,7 @@ import org.json.JSONArray import org.json.JSONObject import java.util.UUID -class ScrcpyProfiles(context: Context) : Settings(context, "ScrcpyProfiles") { +class ScrcpyProfiles(context: Context): Settings(context, "ScrcpyProfiles") { companion object { private val PROFILES_JSON = Pair( stringPreferencesKey("profiles_json"), @@ -36,7 +36,7 @@ class ScrcpyProfiles(context: Context) : Settings(context, "ScrcpyProfiles") { private fun stateFromPreferences(preferences: androidx.datastore.preferences.core.Preferences): State { val raw = preferences.read(PROFILES_JSON) return normalizeState( - runCatching { decodeState(raw) }.getOrNull() ?: State(emptyList()) + runCatching { decodeState(raw) }.getOrNull() ?: State(emptyList()), ) } @@ -107,8 +107,8 @@ class ScrcpyProfiles(context: Context) : Settings(context, "ScrcpyProfiles") { current.copy( profiles = current.profiles.map { if (it.id == id) updated else it - } - ) + }, + ), ) saveState(next) return next.profiles.firstOrNull { it.id == id } @@ -120,8 +120,8 @@ class ScrcpyProfiles(context: Context) : Settings(context, "ScrcpyProfiles") { if (current.profiles.none { it.id == id }) return false val next = normalizeState( current.copy( - profiles = current.profiles.filterNot { it.id == id } - ) + profiles = current.profiles.filterNot { it.id == id }, + ), ) saveState(next) return true @@ -213,7 +213,7 @@ class ScrcpyProfiles(context: Context) : Settings(context, "ScrcpyProfiles") { JSONObject() .put("id", profile.id) .put("name", profile.name) - .put("bundle", encodeBundleToJson(profile.bundle)) + .put("bundle", encodeBundleToJson(profile.bundle)), ) } return array.toString() @@ -236,7 +236,7 @@ class ScrcpyProfiles(context: Context) : Settings(context, "ScrcpyProfiles") { name = name.ifBlank { textNewProfile }, bundle = decodeBundleFromJson(item.optJSONObject("bundle")), isBuiltinGlobal = id == ScrcpyOptions.GLOBAL_PROFILE_ID, - ) + ), ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/Settings.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/Settings.kt index 48b8291..fcd5269 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/Settings.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/storage/Settings.kt @@ -2,11 +2,7 @@ package io.github.miuzarte.scrcpyforandroid.storage import android.content.Context import android.util.Log -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.datastore.core.DataStore import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler @@ -14,17 +10,8 @@ import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.emptyPreferences import androidx.datastore.preferences.preferencesDataStore -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* import kotlin.reflect.KProperty import kotlin.time.Duration.Companion.milliseconds @@ -37,7 +24,7 @@ abstract class Settings( ReplaceFileCorruptionHandler { Log.e(TAG, "Preferences corrupted, resetting.", it) emptyPreferences() - } + }, ) { private val settingsScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) @@ -56,7 +43,7 @@ abstract class Settings( } protected fun bundleField(pair: Pair, selector: (B) -> T): BundleField = - object : BundleField { + object: BundleField { override suspend fun persist(settings: Settings, current: B, new: B) { val currentValue = selector(current) val newValue = selector(new) @@ -70,7 +57,7 @@ abstract class Settings( * 设置项委托类,自动提供 get/set/observe/asState/asMutableState 方法 */ inner class SettingProperty( - val pair: Pair + val pair: Pair, ) { // 创建时注册自身 init { @@ -107,7 +94,7 @@ abstract class Settings( private val Context.dataStore: DataStore by preferencesDataStore( name = this.name, corruptionHandler = corruptionHandler, - scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + scope = CoroutineScope(Dispatchers.IO + SupervisorJob()), ) // 对外暴露的 DataStore 实例 @@ -121,7 +108,7 @@ abstract class Settings( .stateIn( scope = settingsScope, started = SharingStarted.Eagerly, - initialValue = runBlocking { loadBundle(reader) } + initialValue = runBlocking { loadBundle(reader) }, ) protected suspend fun loadBundle(reader: (Preferences) -> B): B = @@ -156,7 +143,7 @@ abstract class Settings( val state = asState(pair) return rememberSaveable(state.value) { - object : MutableState { + object: MutableState { override var value: T get() = state.value set(newValue) { diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/ThemePreferences.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/ThemePreferences.kt index 918bd76..2795105 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/ThemePreferences.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/ThemePreferences.kt @@ -6,11 +6,7 @@ import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.RectangleShape 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.rememberLayerBackdrop -import top.yukonga.miuix.kmp.blur.textureBlur +import top.yukonga.miuix.kmp.blur.* import top.yukonga.miuix.kmp.shader.isRenderEffectSupported import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/FloatingBottomBar.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/FloatingBottomBar.kt index 2a31724..6454e45 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/FloatingBottomBar.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/FloatingBottomBar.kt @@ -5,30 +5,9 @@ import androidx.compose.animation.core.EaseOut import androidx.compose.animation.core.spring import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow -import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -84,7 +63,7 @@ fun RowScope.FloatingBottomBarItem( interactionSource = null, indication = null, role = Role.Tab, - onClick = onClick + onClick = onClick, ) .fillMaxHeight() .weight(1f) @@ -95,7 +74,7 @@ fun RowScope.FloatingBottomBarItem( }, verticalArrangement = Arrangement.spacedBy(1.dp, Alignment.CenterVertically), horizontalAlignment = Alignment.CenterHorizontally, - content = content + content = content, ) } @@ -184,13 +163,13 @@ fun FloatingBottomBar( if (tabWidthPx > 0) { updateValue( (targetValue + dragAmount.x / tabWidthPx * if (isLtr) 1f else -1f) - .fastCoerceIn(0f, (tabsCount - 1).toFloat()) + .fastCoerceIn(0f, (tabsCount - 1).toFloat()), ) animationScope.launch { offsetAnimation.snapTo(offsetAnimation.value + dragAmount.x) } } - } + }, ).also { holder.instance = it } } @@ -214,15 +193,15 @@ fun FloatingBottomBar( } else { size.width - (dampedDragAnimation.value + 0.5f) * tabWidthPx + panelOffset }, - size.height / 2f + size.height / 2f, ) - } + }, ) } Box( modifier = modifier.width(IntrinsicSize.Min), - contentAlignment = Alignment.CenterStart + contentAlignment = Alignment.CenterStart, ) { Row( Modifier @@ -235,7 +214,7 @@ fun FloatingBottomBar( .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null, - onClick = {} + onClick = {}, ) .drawBackdrop( backdrop = backdrop, @@ -263,20 +242,20 @@ fun FloatingBottomBar( scaleY = scale } }, - onDrawSurface = { drawRect(containerColor) } + onDrawSurface = { drawRect(containerColor) }, ) .then(if (isBlurEnabled) interactiveHighlight.modifier else Modifier) .height(64.dp) .padding(4.dp), verticalAlignment = Alignment.CenterVertically, - content = content + content = content, ) CompositionLocalProvider( LocalFloatingBottomBarTabScale provides { if (isBlurEnabled) lerp(1f, 1.2f, dampedDragAnimation.pressProgress) else 1f - } + }, ) { Row( Modifier @@ -298,14 +277,14 @@ fun FloatingBottomBar( highlight = { Highlight.Default.copy(alpha = if (isBlurEnabled) dampedDragAnimation.pressProgress else 0f) }, - onDrawSurface = { drawRect(containerColor) } + onDrawSurface = { drawRect(containerColor) }, ) .then(if (isBlurEnabled) interactiveHighlight.modifier else Modifier) .height(56.dp) .padding(horizontal = 4.dp) .graphicsLayer(colorFilter = ColorFilter.tint(accentColor)), verticalAlignment = Alignment.CenterVertically, - content = content + content = content, ) } @@ -343,7 +322,7 @@ fun FloatingBottomBar( innerShadow = { InnerShadow( radius = 8f.dp * dampedDragAnimation.pressProgress, - alpha = if (isBlurEnabled) dampedDragAnimation.pressProgress else 0f + alpha = if (isBlurEnabled) dampedDragAnimation.pressProgress else 0f, ) }, layerBlock = { @@ -364,15 +343,15 @@ fun FloatingBottomBar( } else { Color.White.copy(0.1f) }, - alpha = 1f - progress + alpha = 1f - progress, ) drawRect( - Color.Black.copy(alpha = 0.03f * progress) + Color.Black.copy(alpha = 0.03f * progress), ) - } + }, ) .height(56.dp) - .width(with(density) { ((totalWidthPx - 8.dp.toPx()) / tabsCount).toDp() }) + .width(with(density) { ((totalWidthPx - 8.dp.toPx()) / tabsCount).toDp() }), ) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/DampedDragAnimation.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/DampedDragAnimation.kt index ca33f4f..c3c85b8 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/DampedDragAnimation.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/DampedDragAnimation.kt @@ -65,7 +65,7 @@ class DampedDragAnimation( onDragCancel = { onDragStopped() release() - } + }, ) { change, dragAmount -> val position = change.position val previousPosition = change.previousPosition @@ -109,7 +109,7 @@ class DampedDragAnimation( launch { valueAnimation.animateTo( targetValue, - valueAnimationSpec + valueAnimationSpec, ) { updateVelocity() } } } @@ -132,7 +132,7 @@ class DampedDragAnimation( private fun updateVelocity() { velocityTracker.addPosition( System.currentTimeMillis(), - Offset(value, 0f) + Offset(value, 0f), ) val targetVelocity = velocityTracker.calculateVelocity().x / (valueRange.endInclusive - valueRange.start) diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/InteractiveHighlight.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/InteractiveHighlight.kt index d904fb3..fbd9986 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/InteractiveHighlight.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/animation/InteractiveHighlight.kt @@ -49,7 +49,7 @@ class InteractiveHighlight( float dist = distance(coord, position); float intensity = smoothstep(radius, radius * 0.5, dist); return color * intensity; - }""" + }""", ) val modifier: Modifier = Modifier.drawWithContent { @@ -57,7 +57,7 @@ class InteractiveHighlight( if (progress > 0f) { drawRect( Color.White.copy(0.06f * progress), - blendMode = BlendMode.Plus + blendMode = BlendMode.Plus, ) shader.apply { val shaderPosition = position(size, positionAnimation.value) @@ -70,7 +70,7 @@ class InteractiveHighlight( } drawRect( ShaderBrush(shader), - blendMode = BlendMode.Plus + blendMode = BlendMode.Plus, ) } @@ -97,7 +97,7 @@ class InteractiveHighlight( launch { pressProgressAnimation.animateTo(0f, pressProgressAnimationSpec) } launch { positionAnimation.animateTo(startPosition, positionAnimationSpec) } } - } + }, ) { change, _ -> animationScope.launch { positionAnimation.snapTo(change.position) } } diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/modifier/DragGestureInspector.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/modifier/DragGestureInspector.kt index 166a1b7..5abd0b7 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/modifier/DragGestureInspector.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/ui/component/miuix/modifier/DragGestureInspector.kt @@ -3,13 +3,7 @@ package io.github.miuzarte.scrcpyforandroid.ui.component.miuix.modifier import androidx.compose.foundation.gestures.awaitEachGesture import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.input.pointer.AwaitPointerEventScope -import androidx.compose.ui.input.pointer.PointerEventPass -import androidx.compose.ui.input.pointer.PointerId -import androidx.compose.ui.input.pointer.PointerInputChange -import androidx.compose.ui.input.pointer.PointerInputScope -import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed -import androidx.compose.ui.input.pointer.positionChange +import androidx.compose.ui.input.pointer.* import androidx.compose.ui.util.fastFirstOrNull suspend fun PointerInputScope.inspectDragGestures( @@ -26,7 +20,7 @@ suspend fun PointerInputScope.inspectDragGestures( onDrag(initialDown, Offset.Zero) val upEvent = drag( pointerId = initialDown.id, - onDrag = { onDrag(it, it.positionChange()) } + onDrag = { onDrag(it, it.positionChange()) }, ) if (upEvent == null) { onDragCancel() diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/AppBottomSheets.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/AppBottomSheets.kt index ecd9e5b..c48d8b7 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/AppBottomSheets.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/AppBottomSheets.kt @@ -2,13 +2,7 @@ package io.github.miuzarte.scrcpyforandroid.widgets import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.sizeIn +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons @@ -22,11 +16,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import io.github.miuzarte.scrcpyforandroid.R 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.IconButton -import top.yukonga.miuix.kmp.basic.Text +import top.yukonga.miuix.kmp.basic.* import top.yukonga.miuix.kmp.icon.MiuixIcons import top.yukonga.miuix.kmp.icon.extended.Store import top.yukonga.miuix.kmp.overlay.OverlayBottomSheet diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/ScrcpyInputSurfaceView.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/ScrcpyInputSurfaceView.kt index 277a21d..7deda17 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/ScrcpyInputSurfaceView.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/ScrcpyInputSurfaceView.kt @@ -13,7 +13,7 @@ class ScrcpyInputSurfaceView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, -) : SurfaceView(context, attrs, defStyleAttr) { +): SurfaceView(context, attrs, defStyleAttr) { interface InputCallbacks { fun handleKeyEvent(event: KeyEvent): Boolean fun handleCommitText(text: CharSequence): Boolean @@ -46,7 +46,7 @@ class ScrcpyInputSurfaceView @JvmOverloads constructor( outAttrs.inputType = InputType.TYPE_CLASS_TEXT outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI - return object : BaseInputConnection(this, false) { + return object: BaseInputConnection(this, false) { override fun commitText(text: CharSequence, newCursorPosition: Int): Boolean { if (inputCallbacks?.handleCommitText(text) == true) return true return super.commitText(text, newCursorPosition) diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/StatusCardModels.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/StatusCardModels.kt index c4c5db4..797cb68 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/StatusCardModels.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/StatusCardModels.kt @@ -1,19 +1,6 @@ package io.github.miuzarte.scrcpyforandroid.widgets -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.Alignment @@ -129,7 +116,7 @@ internal fun StatusCardLayout( Column( modifier = Modifier .weight(1f) - .fillMaxHeight() + .fillMaxHeight(), ) { StatusMetricCard( modifier = Modifier diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/TerminalInputView.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/TerminalInputView.kt index ebcb2e2..64c9f6a 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/TerminalInputView.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/TerminalInputView.kt @@ -13,7 +13,7 @@ class TerminalInputView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, -) : View(context, attrs, defStyleAttr) { +): View(context, attrs, defStyleAttr) { interface InputCallbacks { fun handleKeyEvent(event: KeyEvent): Boolean fun handleCommitText(text: CharSequence): Boolean @@ -51,7 +51,7 @@ class TerminalInputView @JvmOverloads constructor( outAttrs.inputType = InputType.TYPE_CLASS_TEXT outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI - return object : BaseInputConnection(this, false) { + return object: BaseInputConnection(this, false) { override fun commitText(text: CharSequence, newCursorPosition: Int): Boolean { if (inputCallbacks?.handleCommitText(text) == true) return true return super.commitText(text, newCursorPosition) diff --git a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/VirtualButtons.kt b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/VirtualButtons.kt index 4ceb6a2..608e0af 100644 --- a/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/VirtualButtons.kt +++ b/app/src/main/java/io/github/miuzarte/scrcpyforandroid/widgets/VirtualButtons.kt @@ -3,48 +3,16 @@ package io.github.miuzarte.scrcpyforandroid.widgets import androidx.annotation.StringRes import androidx.compose.foundation.border import androidx.compose.foundation.gestures.detectDragGestures -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.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.automirrored.rounded.VolumeDown import androidx.compose.material.icons.automirrored.rounded.VolumeOff import androidx.compose.material.icons.automirrored.rounded.VolumeUp -import androidx.compose.material.icons.rounded.Apps -import androidx.compose.material.icons.rounded.ContentPaste -import androidx.compose.material.icons.rounded.DashboardCustomize -import androidx.compose.material.icons.rounded.Home -import androidx.compose.material.icons.rounded.Keyboard -import androidx.compose.material.icons.rounded.Menu -import androidx.compose.material.icons.rounded.Notifications -import androidx.compose.material.icons.rounded.Password -import androidx.compose.material.icons.rounded.PowerSettingsNew -import androidx.compose.material.icons.rounded.Screenshot -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.material.icons.rounded.* +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color @@ -69,20 +37,13 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch -import top.yukonga.miuix.kmp.basic.Button -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.ListPopupColumn -import top.yukonga.miuix.kmp.basic.ListPopupDefaults -import top.yukonga.miuix.kmp.basic.PopupPositionProvider -import top.yukonga.miuix.kmp.basic.SpinnerItemImpl -import top.yukonga.miuix.kmp.basic.Text +import top.yukonga.miuix.kmp.basic.* import top.yukonga.miuix.kmp.icon.MiuixIcons import top.yukonga.miuix.kmp.icon.extended.More import top.yukonga.miuix.kmp.overlay.OverlayListPopup import top.yukonga.miuix.kmp.theme.MiuixTheme.colorScheme +import kotlin.ranges.coerceAtLeast +import kotlin.ranges.coerceIn enum class VirtualButtonAction( val id: String, @@ -94,97 +55,97 @@ enum class VirtualButtonAction( "more", R.string.vb_more, MiuixIcons.More, - null + null, ), HOME( "home", R.string.vb_home, Icons.Rounded.Home, - UiAndroidKeycodes.HOME + UiAndroidKeycodes.HOME, ), BACK( "back", R.string.vb_back, Icons.AutoMirrored.Rounded.ArrowBack, - UiAndroidKeycodes.BACK + UiAndroidKeycodes.BACK, ), APP_SWITCH( "app_switch", R.string.vb_app_switch, Icons.Rounded.Apps, - UiAndroidKeycodes.APP_SWITCH + UiAndroidKeycodes.APP_SWITCH, ), MENU( "menu", R.string.vb_menu, Icons.Rounded.Menu, - UiAndroidKeycodes.MENU + UiAndroidKeycodes.MENU, ), NOTIFICATION( "notification", R.string.vb_notifications, Icons.Rounded.Notifications, - UiAndroidKeycodes.NOTIFICATION + UiAndroidKeycodes.NOTIFICATION, ), VOLUME_UP( "volume_up", R.string.vb_volume_up, Icons.AutoMirrored.Rounded.VolumeUp, - UiAndroidKeycodes.VOLUME_UP + UiAndroidKeycodes.VOLUME_UP, ), VOLUME_DOWN( "volume_down", R.string.vb_volume_down, Icons.AutoMirrored.Rounded.VolumeDown, - UiAndroidKeycodes.VOLUME_DOWN + UiAndroidKeycodes.VOLUME_DOWN, ), VOLUME_MUTE( "volume_mute", R.string.vb_volume_mute, Icons.AutoMirrored.Rounded.VolumeOff, - UiAndroidKeycodes.VOLUME_MUTE + UiAndroidKeycodes.VOLUME_MUTE, ), POWER( "power", R.string.vb_lock_screen, Icons.Rounded.PowerSettingsNew, - UiAndroidKeycodes.POWER + UiAndroidKeycodes.POWER, ), SCREENSHOT( "screenshot", R.string.vb_screenshot, Icons.Rounded.Screenshot, - UiAndroidKeycodes.SYSRQ + UiAndroidKeycodes.SYSRQ, ), PASSWORD_INPUT( "password_input", R.string.vb_fill_password, Icons.Rounded.Password, - null + null, ), ALL_APPS( "all_apps", R.string.vb_all_apps, Icons.Rounded.Apps, - null + null, ), RECENT_TASKS( "recent_tasks", R.string.vb_recent_tasks, Icons.Rounded.DashboardCustomize, - null + null, ), TOGGLE_IME( "toggle_ime", R.string.vb_toggle_ime, Icons.Rounded.Keyboard, - null + null, ), PASTE_LOCAL_CLIPBOARD( "paste_local_clipboard", R.string.vb_paste_clipboard, Icons.Rounded.ContentPaste, - null + null, ); } @@ -418,7 +379,7 @@ class VirtualButtonBar( Icon( imageVector = action.icon, contentDescription = stringResource(action.titleResId), - tint = Color.White + tint = Color.White, ) } @@ -475,7 +436,7 @@ class VirtualButtonBar( Icon( imageVector = action.icon, contentDescription = stringResource(action.titleResId), - tint = Color.White + tint = Color.White, ) } @@ -546,7 +507,7 @@ class VirtualButtonBar( latest.copy( fullscreenFloatingButtonXFraction = offsetXFraction, fullscreenFloatingButtonYFraction = offsetYFraction, - ) + ), ) } } @@ -637,7 +598,7 @@ class VirtualButtonBar( ) } else { Modifier - } + }, ), ) } @@ -785,7 +746,7 @@ class VirtualButtonBar( private class BottomSafeContextMenuPositionProvider( private val bottomPadding: Dp, - ) : PopupPositionProvider { + ): PopupPositionProvider { private val delegate = ListPopupDefaults.ContextMenuPositionProvider override fun calculatePosition(