Merge pull request #5 from msomu/main

Fix Settings UI reactivity, resolve compiler warnings, update .gitignore
This commit is contained in:
Somasundaram M
2026-02-18 08:46:41 +05:30
committed by GitHub
6 changed files with 32 additions and 15 deletions

2
android/.gitignore vendored
View File

@@ -7,6 +7,8 @@
/.idea/workspace.xml /.idea/workspace.xml
/.idea/navEditor.xml /.idea/navEditor.xml
/.idea/assetWizardSettings.xml /.idea/assetWizardSettings.xml
/.idea/misc.xml
/.idea/junie.xml
.DS_Store .DS_Store
/build /build
/captures /captures

10
android/.idea/misc.xml generated
View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="temurin-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@@ -64,6 +64,7 @@ dependencies {
// Lifecycle service // Lifecycle service
implementation(libs.lifecycle.service) implementation(libs.lifecycle.service)
implementation(libs.lifecycle.runtime.compose)
// Navigation // Navigation
implementation(libs.navigation.compose) implementation(libs.navigation.compose)

View File

@@ -1,9 +1,12 @@
package com.thisux.droidclaw.capture package com.thisux.droidclaw.capture
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.PixelFormat import android.graphics.PixelFormat
import androidx.core.graphics.createBitmap
import androidx.core.graphics.get
import android.hardware.display.DisplayManager import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay import android.hardware.display.VirtualDisplay
import android.media.ImageReader import android.media.ImageReader
@@ -19,16 +22,19 @@ class ScreenCaptureManager(private val context: Context) {
companion object { companion object {
private const val TAG = "ScreenCapture" private const val TAG = "ScreenCapture"
const val REQUEST_CODE = 1001
val isAvailable = MutableStateFlow(false) val isAvailable = MutableStateFlow(false)
// Stores MediaProjection consent for use by ConnectionService // Stores MediaProjection consent for use by ConnectionService
var consentResultCode: Int? = null var consentResultCode: Int? = null
var consentData: Intent? = null var consentData: Intent? = null
// Expose consent as state so UI can react immediately
val hasConsentState = MutableStateFlow(false)
fun storeConsent(resultCode: Int, data: Intent?) { fun storeConsent(resultCode: Int, data: Intent?) {
consentResultCode = resultCode consentResultCode = resultCode
consentData = data consentData = data
hasConsentState.value = (resultCode == Activity.RESULT_OK && data != null)
} }
fun hasConsent(): Boolean = consentResultCode != null && consentData != null fun hasConsent(): Boolean = consentResultCode != null && consentData != null
@@ -86,7 +92,7 @@ class ScreenCaptureManager(private val context: Context) {
val rowStride = planes[0].rowStride val rowStride = planes[0].rowStride
val rowPadding = rowStride - pixelStride * image.width val rowPadding = rowStride - pixelStride * image.width
val bitmap = Bitmap.createBitmap( val bitmap = createBitmap(
image.width + rowPadding / pixelStride, image.width + rowPadding / pixelStride,
image.height, image.height,
Bitmap.Config.ARGB_8888 Bitmap.Config.ARGB_8888
@@ -119,7 +125,7 @@ class ScreenCaptureManager(private val context: Context) {
bitmap.width - 1 to bitmap.height - 1, bitmap.width - 1 to bitmap.height - 1,
bitmap.width / 2 to bitmap.height / 2 bitmap.width / 2 to bitmap.height / 2
) )
return points.all { (x, y) -> bitmap.getPixel(x, y) == android.graphics.Color.BLACK } return points.all { (x, y) -> bitmap[x, y] == android.graphics.Color.BLACK }
} }
fun release() { fun release() {

View File

@@ -26,6 +26,7 @@ import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -36,8 +37,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import com.thisux.droidclaw.DroidClawApp import com.thisux.droidclaw.DroidClawApp
import com.thisux.droidclaw.accessibility.DroidClawAccessibilityService import com.thisux.droidclaw.accessibility.DroidClawAccessibilityService
import com.thisux.droidclaw.capture.ScreenCaptureManager import com.thisux.droidclaw.capture.ScreenCaptureManager
@@ -58,8 +62,21 @@ fun SettingsScreen() {
val isAccessibilityEnabled by DroidClawAccessibilityService.isRunning.collectAsState() val isAccessibilityEnabled by DroidClawAccessibilityService.isRunning.collectAsState()
val isCaptureAvailable by ScreenCaptureManager.isAvailable.collectAsState() val isCaptureAvailable by ScreenCaptureManager.isAvailable.collectAsState()
val hasCaptureConsent = isCaptureAvailable || ScreenCaptureManager.hasConsent() val hasConsent by ScreenCaptureManager.hasConsentState.collectAsState()
val isBatteryExempt = remember { BatteryOptimization.isIgnoringBatteryOptimizations(context) } val hasCaptureConsent = isCaptureAvailable || hasConsent
var isBatteryExempt by remember { mutableStateOf(BatteryOptimization.isIgnoringBatteryOptimizations(context)) }
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) {
isBatteryExempt = BatteryOptimization.isIgnoringBatteryOptimizations(context)
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
}
val projectionLauncher = rememberLauncherForActivityResult( val projectionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult() ActivityResultContracts.StartActivityForResult()

View File

@@ -39,6 +39,7 @@ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-
kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" } kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" }
datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" } datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" }
lifecycle-service = { group = "androidx.lifecycle", name = "lifecycle-service", version.ref = "lifecycleService" } lifecycle-service = { group = "androidx.lifecycle", name = "lifecycle-service", version.ref = "lifecycleService" }
lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleService" }
navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
compose-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended", version.ref = "composeIconsExtended" } compose-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended", version.ref = "composeIconsExtended" }