diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessUtils.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessController.kt similarity index 68% rename from app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessUtils.kt rename to app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessController.kt index d04313d..2acef95 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessUtils.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessController.kt @@ -15,10 +15,11 @@ fun rememberBrightnessController(): BrightnessController { val window = (LocalContext.current as? Activity)?.window var isOn by remember { mutableStateOf(false) } - LaunchedEffect(isOn) { + // Sync side-effect: no coroutine needed + SideEffect { window?.attributes = window?.attributes?.apply { - screenBrightness = if (isOn) 1f - else WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE + screenBrightness = if (isOn) WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL + else WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE } } @@ -30,9 +31,9 @@ fun rememberBrightnessController(): BrightnessController { } } - return remember(isOn) { - BrightnessController(isOn = isOn, toggle = { isOn = !isOn }) - } + // No remember needed — BrightnessController is a tiny data class, + // and this composable already recomposes only when isOn changes. + return BrightnessController(isOn = isOn, toggle = { isOn = !isOn }) } data class BrightnessController( diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/receive/QrDisplayCard.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/QrDisplayCard.kt similarity index 99% rename from app/src/main/java/com/bitcointxoko/gudariwallet/ui/receive/QrDisplayCard.kt rename to app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/QrDisplayCard.kt index e45d52e..6f9e0e1 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/receive/QrDisplayCard.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/QrDisplayCard.kt @@ -1,4 +1,4 @@ -package com.bitcointxoko.gudariwallet.ui.receive +package com.bitcointxoko.gudariwallet.ui.common import android.content.ClipData import android.graphics.Bitmap diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcPairingDialog.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcPairingDialog.kt index 2a1f0d0..fdd03e9 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcPairingDialog.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcPairingDialog.kt @@ -1,10 +1,7 @@ package com.bitcointxoko.gudariwallet.ui.nwc -import android.app.Activity import android.content.ActivityNotFoundException import android.content.Intent -import android.view.WindowManager -import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth @@ -13,18 +10,12 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -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.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.core.net.toUri import com.bitcointxoko.gudariwallet.ui.common.rememberBrightnessController -import com.bitcointxoko.gudariwallet.ui.receive.QrDisplayCard +import com.bitcointxoko.gudariwallet.ui.common.QrDisplayCard @Composable internal fun NwcPairingUrlDialog( diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/receive/ReceiveScreen.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/receive/ReceiveScreen.kt index 9bffb5a..39ccd6a 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/receive/ReceiveScreen.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/receive/ReceiveScreen.kt @@ -1,7 +1,5 @@ package com.bitcointxoko.gudariwallet.ui.receive -import android.app.Activity -import android.view.WindowManager import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -58,14 +56,13 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitcointxoko.gudariwallet.LocalAppStrings import com.bitcointxoko.gudariwallet.ui.ReceiveState -import com.bitcointxoko.gudariwallet.ui.SendState import com.bitcointxoko.gudariwallet.ui.WalletViewModel +import com.bitcointxoko.gudariwallet.ui.common.QrDisplayCard +import com.bitcointxoko.gudariwallet.ui.common.rememberBrightnessController import com.bitcointxoko.gudariwallet.ui.components.UnitWheelPicker import com.bitcointxoko.gudariwallet.ui.nfc.NfcViewModel import com.bitcointxoko.gudariwallet.util.buildUpTaps -import com.bitcointxoko.gudariwallet.util.doubleTap import com.bitcointxoko.gudariwallet.util.fiatLabel -import com.bitcointxoko.gudariwallet.util.heavyClick import kotlinx.coroutines.delay @Composable @@ -74,32 +71,17 @@ fun ReceiveScreen( nfcVm : NfcViewModel, onNavigateToPaymentDetail: (checkingId: String) -> Unit ) { - val strings = LocalAppStrings.current + val strings = LocalAppStrings.current + val context = LocalContext.current + val brightness = rememberBrightnessController() + var showAddress by remember { mutableStateOf(false) } val receiveState by vm.receiveState.collectAsStateWithLifecycle() val lightningAddress by vm.lightningAddress.collectAsStateWithLifecycle() val fiatRate by vm.fiatSatsPerUnit.collectAsStateWithLifecycle() val fiatCurrency by vm.selectedCurrency.collectAsStateWithLifecycle() - val context = LocalContext.current - val window = (context as Activity).window - val originalBrightness = remember { window.attributes.screenBrightness } - var brightnessOn by remember { mutableStateOf(false) } - var showAddress by remember { mutableStateOf(false) } - - val onToggleBrightness = { - val lp = window.attributes - lp.screenBrightness = if (!brightnessOn) - WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL - else originalBrightness - window.attributes = lp - brightnessOn = !brightnessOn - } - DisposableEffect(Unit) { onDispose { - val lp = window.attributes - lp.screenBrightness = originalBrightness - window.attributes = lp nfcVm.stopEmulating() vm.resetReceiveState() } @@ -141,8 +123,8 @@ fun ReceiveScreen( lightningAddress = lightningAddress, showAddress = showAddress, onToggleAddress = { showAddress = !showAddress }, - brightnessOn = brightnessOn, - onToggleBrightness = onToggleBrightness, + brightnessOn = brightness.isOn, + onToggleBrightness = brightness.toggle, isLoading = receiveState is ReceiveState.AwaitingInvoice, onCreateInvoice = { amountSats, memo -> vm.createInvoice( @@ -216,8 +198,8 @@ fun ReceiveScreen( state = receiveState as ReceiveState.InvoiceReady, fiatRate = fiatRate, fiatCurrency = fiatCurrency, - brightnessOn = brightnessOn, - onToggleBrightness = onToggleBrightness, + brightnessOn = brightness.isOn, + onToggleBrightness = brightness.toggle, nfcVm = nfcVm, onReset = { vm.resetReceiveState() } ) @@ -438,12 +420,12 @@ private fun ReceiveIdleContent( Spacer(Modifier.height(12.dp)) QrDisplayCard( - content = lightningAddress, + content = lightningAddress, contentDescription = strings.lightningAddressQrCode, // ← "Lightning address QR code" - clipLabel = strings.lightningAddressLabel, // ← "Lightning Address" - shareTitle = strings.shareLightningAddress, // ← "Share Lightning Address" - textToCopy = lightningAddress, - brightnessOn = brightnessOn, + clipLabel = strings.lightningAddressLabel, // ← "Lightning Address" + shareTitle = strings.shareLightningAddress, // ← "Share Lightning Address" + textToCopy = lightningAddress, + brightnessOn = brightnessOn, onToggleBrightness = onToggleBrightness ) } @@ -512,7 +494,7 @@ private fun AmountStepContent( val number = amountText.trim().toDoubleOrNull() ?: return@remember null when (activeUnit) { AmountUnit.SATS -> fiatLabel(number.toLong(), fiatRate, fiatCurrency) - AmountUnit.FIAT -> "≈ ${(number * fiatRate!!).toLong()} sats" + AmountUnit.FIAT -> "≈ ${(number * fiatRate).toLong()} sats" } } @@ -560,7 +542,7 @@ private fun AmountStepContent( ) UnitWheelPicker( - units = if (showFiatToggle) listOf(strings.sats, fiatCurrency!!) else listOf(strings.sats), + units = if (showFiatToggle) listOf(strings.sats, fiatCurrency) else listOf(strings.sats), selectedIndex = if (activeUnit == AmountUnit.SATS) 0 else 1, onIndexSelected = { newIndex -> val newUnit = if (newIndex == 0) AmountUnit.SATS else AmountUnit.FIAT @@ -682,23 +664,23 @@ private fun ReceiveInvoiceContent( } QrDisplayCard( - content = state.bolt11.uppercase(), + content = state.bolt11.uppercase(), contentDescription = strings.lightningInvoiceQrCode, // ← "Lightning invoice QR code" - clipLabel = strings.invoiceLabel, // ← "Invoice" - shareTitle = strings.shareInvoice, // ← "Share Invoice" - textToCopy = state.bolt11, - brightnessOn = brightnessOn, + clipLabel = strings.invoiceLabel, // ← "Invoice" + shareTitle = strings.shareInvoice, // ← "Share Invoice" + textToCopy = state.bolt11, + brightnessOn = brightnessOn, onToggleBrightness = onToggleBrightness, - isNfcEmulating = isEmulating, - onToggleNfc = { + isNfcEmulating = isEmulating, + onToggleNfc = { if (isEmulating) nfcVm.stopEmulating() - else nfcVm.startEmulating("lightning:${state.bolt11}") + else nfcVm.startEmulating("lightning:${state.bolt11}") }, - nfcEnabled = !isExpired, - modifier = Modifier + nfcEnabled = !isExpired, + modifier = Modifier .weight(1f) .fillMaxWidth(), - qrModifier = Modifier + qrModifier = Modifier .fillMaxWidth() .weight(1f) )