refactor: extract BrightnessUtils, use snackbar instead of toast

This commit is contained in:
2026-06-10 18:18:14 +02:00
parent 9ba408e157
commit e5f8156ecf
3 changed files with 68 additions and 41 deletions
@@ -0,0 +1,41 @@
package com.bitcointxoko.gudariwallet.ui.common
import android.app.Activity
import android.view.WindowManager
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
/**
* Manages screen brightness for QR-display screens.
* Returns a [BrightnessController] with [isOn] state and a [toggle] callback.
* Restores system brightness unconditionally when it leaves composition.
*/
@Composable
fun rememberBrightnessController(): BrightnessController {
val window = (LocalContext.current as? Activity)?.window
var isOn by remember { mutableStateOf(false) }
LaunchedEffect(isOn) {
window?.attributes = window?.attributes?.apply {
screenBrightness = if (isOn) 1f
else WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
}
DisposableEffect(Unit) {
onDispose {
window?.attributes = window?.attributes?.apply {
screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
}
}
return remember(isOn) {
BrightnessController(isOn = isOn, toggle = { isOn = !isOn })
}
}
data class BrightnessController(
val isOn : Boolean,
val toggle : () -> Unit
)
@@ -23,35 +23,19 @@ 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
@Composable
internal fun NwcPairingUrlDialog(
url : String,
onDismiss : () -> Unit
onDismiss : () -> Unit,
onNoAppFound : () -> Unit
) {
// Brightness state lives here so the dialog owns the screen-brightness side-effect
var brightnessOn by remember { mutableStateOf(false) }
val window = (LocalContext.current as? Activity)?.window
val brightness = rememberBrightnessController()
val context = LocalContext.current
// Boost / restore screen brightness when the toggle changes
LaunchedEffect(brightnessOn) {
window?.attributes = window.attributes?.apply {
screenBrightness = if (brightnessOn) 1f
else WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
}
// Restore brightness unconditionally when the dialog leaves composition
DisposableEffect(Unit) {
onDispose {
window?.attributes = window.attributes?.apply {
screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
}
}
AlertDialog(
onDismissRequest = onDismiss,
title = { Text("Connection created") },
@@ -63,31 +47,24 @@ internal fun NwcPairingUrlDialog(
color = MaterialTheme.colorScheme.onSurfaceVariant
)
QrDisplayCard(
modifier = Modifier.fillMaxWidth(),
content = url,
contentDescription = "NWC pairing QR code",
clipLabel = "NWC connection string",
shareTitle = "Share NWC connection string",
textToCopy = url,
brightnessOn = brightnessOn,
onToggleBrightness = { brightnessOn = !brightnessOn },
// No NFC for a one-shot pairing string
isNfcEmulating = null,
qrModifier = Modifier.fillMaxWidth(),
onOpenUri = {
modifier = Modifier.fillMaxWidth(),
content = url,
contentDescription = "NWC pairing QR code",
clipLabel = "NWC connection string",
shareTitle = "Share NWC connection string",
textToCopy = url,
brightnessOn = brightness.isOn,
onToggleBrightness = brightness.toggle,
isNfcEmulating = null,
qrModifier = Modifier.fillMaxWidth(),
onOpenUri = {
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
try {
context.startActivity(
Intent.createChooser(intent, "Open in app")
)
} catch (e: ActivityNotFoundException) {
// No app installed that handles nostr+walletconnect://
// Show a snackbar / toast as appropriate for your app
Toast.makeText(
context,
"No compatible app found", // "No compatible app found"
Toast.LENGTH_SHORT
).show()
onNoAppFound() // #17: no Toast — caller handles it
}
}
)
@@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -27,6 +28,8 @@ fun NwcScreen(
val pairingUrl by viewModel.pairingUrl.collectAsStateWithLifecycle()
val showAddSheet by viewModel.showAddSheet.collectAsStateWithLifecycle()
val pendingDeletePubkey by viewModel.pendingDeletePubkey.collectAsStateWithLifecycle()
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
// ── Shared refresh lambda (item #13) ──────────────────────────────────────
val refresh = { viewModel.loadConnections(includeExpired = true) }
@@ -46,7 +49,8 @@ fun NwcScreen(
FloatingActionButton(onClick = { viewModel.openAddSheet() }) {
Icon(Icons.Default.Add, contentDescription = "Add connection")
}
}
},
snackbarHost = { SnackbarHost(snackbarHostState) }
) { innerPadding ->
val isRefreshing = uiState is NwcUiState.Loading
@@ -127,7 +131,12 @@ fun NwcScreen(
pairingUrl?.let { url ->
NwcPairingUrlDialog(
url = url,
onDismiss = { viewModel.clearPairingUrl() }
onDismiss = { viewModel.clearPairingUrl() },
onNoAppFound = {
scope.launch {
snackbarHostState.showSnackbar("No compatible app found")
}
}
)
}