diff --git a/app/src/main/java/to/bitkit/ui/ContentView.kt b/app/src/main/java/to/bitkit/ui/ContentView.kt index 26b41298f..dd32db01e 100644 --- a/app/src/main/java/to/bitkit/ui/ContentView.kt +++ b/app/src/main/java/to/bitkit/ui/ContentView.kt @@ -64,8 +64,6 @@ import to.bitkit.ui.screens.profile.CreateProfileScreen import to.bitkit.ui.screens.profile.ProfileIntroScreen import to.bitkit.ui.screens.recovery.RecoveryMnemonicScreen import to.bitkit.ui.screens.recovery.RecoveryModeScreen -import to.bitkit.ui.screens.scanner.QrScanningScreen -import to.bitkit.ui.screens.scanner.SCAN_REQUEST_KEY import to.bitkit.ui.screens.settings.DevSettingsScreen import to.bitkit.ui.screens.settings.FeeSettingsScreen import to.bitkit.ui.screens.settings.LdkDebugScreen @@ -173,13 +171,12 @@ import to.bitkit.ui.sheets.GiftSheet import to.bitkit.ui.sheets.HighBalanceWarningSheet import to.bitkit.ui.sheets.LnurlAuthSheet import to.bitkit.ui.sheets.PinSheet +import to.bitkit.ui.sheets.QrScanningSheet import to.bitkit.ui.sheets.QuickPayIntroSheet import to.bitkit.ui.sheets.SendSheet import to.bitkit.ui.sheets.UpdateSheet -import to.bitkit.ui.theme.TRANSITION_SHEET_MS import to.bitkit.ui.utils.AutoReadClipboardHandler import to.bitkit.ui.utils.RequestNotificationPermissions -import to.bitkit.ui.utils.Transitions import to.bitkit.ui.utils.composableWithDefaultTransitions import to.bitkit.ui.utils.navigationWithDefaultTransitions import to.bitkit.utils.Logger @@ -402,6 +399,7 @@ fun ContentView( ) is Sheet.Gift -> GiftSheet(sheet, appViewModel) + Sheet.QrScanner -> QrScanningSheet(appViewModel) is Sheet.TimedSheet -> { when (sheet.type) { TimedSheetType.APP_UPDATE -> { @@ -475,7 +473,7 @@ fun ContentView( TabBar( onSendClick = { appViewModel.showSheet(Sheet.Send()) }, onReceiveClick = { appViewModel.showSheet(Sheet.Receive) }, - onScanClick = { navController.navigateToScanner() }, + onScanClick = { appViewModel.showScannerSheet() }, modifier = Modifier.align(Alignment.BottomCenter) ) } @@ -542,7 +540,6 @@ private fun RootNavHost( cjitDetailSettings(navController) lightningConnections(navController) activityItem(activityListViewModel, navController) - qrScanner(appViewModel, navController) authCheck(navController) logs(navController) suggestions(navController) @@ -684,7 +681,7 @@ private fun RootNavHost( } composableWithDefaultTransitions { FundingAdvancedScreen( - onLnurl = { navController.navigateToScanner() }, + onLnurl = { appViewModel.showScannerSheet() }, onManual = { navController.navigate(Routes.ExternalNav) }, onBackClick = { navController.popBackStack() }, ) @@ -699,10 +696,13 @@ private fun RootNavHost( ExternalConnectionScreen( route = route, - savedStateHandle = it.savedStateHandle, viewModel = viewModel, onNodeConnected = { navController.navigate(Routes.ExternalAmount) }, - onScanClick = { navController.navigateToScanner(isCalledForResult = true) }, + onScanClick = { + appViewModel.showScannerSheet { + viewModel.parseNodeUri(it) + } + }, onBackClick = { navController.popBackStack() }, ) } @@ -880,7 +880,7 @@ private fun NavGraphBuilder.settings( VssDebugScreen(navController) } composableWithDefaultTransitions { - ProbingToolScreen(it.savedStateHandle, navController) + ProbingToolScreen(navController) } composableWithDefaultTransitions { FeeSettingsScreen(navController) @@ -1005,10 +1005,10 @@ private fun NavGraphBuilder.advancedSettings(navController: NavHostController) { CoinSelectPreferenceScreen(navController) } composableWithDefaultTransitions { - ElectrumConfigScreen(it.savedStateHandle, navController) + ElectrumConfigScreen(navController) } composableWithDefaultTransitions { - RgsServerScreen(it.savedStateHandle, navController) + RgsServerScreen(navController) } composableWithDefaultTransitions { AddressTypePreferenceScreen(navController) @@ -1200,23 +1200,6 @@ private fun NavGraphBuilder.activityItem( } } -private fun NavGraphBuilder.qrScanner( - appViewModel: AppViewModel, - navController: NavHostController, -) { - composableWithDefaultTransitions( - enterTransition = { Transitions.slideInVertically }, - popExitTransition = { Transitions.slideOutVertically }, - ) { - QrScanningScreen(navController = navController) { qrCode -> - appViewModel.onScanResult( - data = qrCode, - delayMs = TRANSITION_SHEET_MS, - ) - } - } -} - private fun NavGraphBuilder.authCheck( navController: NavHostController, ) { @@ -1617,13 +1600,6 @@ fun NavController.navigateToActivityExplore(id: String) = navigate( route = Routes.ActivityExplore(id), ) -fun NavController.navigateToScanner(isCalledForResult: Boolean = false) { - if (isCalledForResult) { - currentBackStackEntry?.savedStateHandle?.set(SCAN_REQUEST_KEY, true) - } - navigate(Routes.QrScanner) -} - fun NavController.navigateToLogDetail(fileName: String) = navigate( route = Routes.LogDetail(fileName), ) @@ -1866,9 +1842,6 @@ sealed interface Routes { @Serializable data class ActivityExplore(val id: String) : Routes - @Serializable - data object QrScanner : Routes - @Serializable data object BuyIntro : Routes diff --git a/app/src/main/java/to/bitkit/ui/components/SheetHost.kt b/app/src/main/java/to/bitkit/ui/components/SheetHost.kt index 3d99fe204..5aa0ab856 100644 --- a/app/src/main/java/to/bitkit/ui/components/SheetHost.kt +++ b/app/src/main/java/to/bitkit/ui/components/SheetHost.kt @@ -46,6 +46,7 @@ sealed interface Sheet { data object ForceTransfer : Sheet data class Gift(val code: String, val amount: ULong) : Sheet data object ConnectionClosed : Sheet + data object QrScanner : Sheet data class TimedSheet(val type: TimedSheetType) : Sheet } diff --git a/app/src/main/java/to/bitkit/ui/screens/scanner/CameraPermissionView.kt b/app/src/main/java/to/bitkit/ui/screens/scanner/CameraPermissionView.kt index 72a3c4937..d6cf1483c 100644 --- a/app/src/main/java/to/bitkit/ui/screens/scanner/CameraPermissionView.kt +++ b/app/src/main/java/to/bitkit/ui/screens/scanner/CameraPermissionView.kt @@ -5,14 +5,12 @@ import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -32,7 +30,6 @@ import to.bitkit.ui.components.PrimaryButton import to.bitkit.ui.components.SecondaryButton import to.bitkit.ui.components.Title import to.bitkit.ui.components.VerticalSpacer -import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.SheetTopBar import to.bitkit.ui.shared.util.gradientBackground import to.bitkit.ui.theme.AppThemeSurface @@ -62,7 +59,6 @@ fun CameraPermissionView( @Composable fun DeniedContent( shouldShowRationale: Boolean, - inSheet: Boolean = false, onClickOpenSettings: () -> Unit = {}, onClickRetry: () -> Unit = {}, onClickPaste: () -> Unit = {}, @@ -70,14 +66,10 @@ fun DeniedContent( ) { Column( modifier = Modifier - .then(if (inSheet) Modifier.gradientBackground() else Modifier.background(Colors.Black)) - .then(if (inSheet) Modifier.navigationBarsPadding() else Modifier.systemBarsPadding()) + .gradientBackground() + .navigationBarsPadding() ) { - if (!inSheet) { - AppTopBar(titleText = null, onBack) - } else { - SheetTopBar(titleText = null, onBack = onBack) - } + SheetTopBar(titleText = null, onBack = onBack) Column( verticalArrangement = Arrangement.Center, @@ -165,14 +157,3 @@ fun PreviewDenied() { DeniedContent(shouldShowRationale = true) } } - -@Preview(showSystemUi = true) -@Composable() -fun PreviewInSheet() { - AppThemeSurface { - DeniedContent( - shouldShowRationale = true, - inSheet = true, - ) - } -} diff --git a/app/src/main/java/to/bitkit/ui/screens/scanner/QrScanningScreen.kt b/app/src/main/java/to/bitkit/ui/screens/scanner/QrScanningScreen.kt index 84d7c76fd..10e4143ae 100644 --- a/app/src/main/java/to/bitkit/ui/screens/scanner/QrScanningScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/scanner/QrScanningScreen.kt @@ -22,7 +22,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon @@ -50,7 +49,6 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.LocalLifecycleOwner -import androidx.navigation.NavController import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberPermissionState import com.google.accompanist.permissions.shouldShowRationale @@ -59,7 +57,6 @@ import com.google.mlkit.vision.barcode.BarcodeScanning import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.common.InputImage import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay import kotlinx.coroutines.withContext import to.bitkit.R import to.bitkit.env.Env @@ -72,7 +69,6 @@ import to.bitkit.ui.components.SecondaryButton import to.bitkit.ui.components.TextInput import to.bitkit.ui.components.VerticalSpacer import to.bitkit.ui.scaffold.AppAlertDialog -import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.SheetTopBar import to.bitkit.ui.shared.util.gradientBackground import to.bitkit.ui.theme.Colors @@ -80,17 +76,14 @@ import to.bitkit.utils.Logger import to.bitkit.viewmodels.AppViewModel import java.util.concurrent.Executors -const val SCAN_REQUEST_KEY = "SCAN_REQUEST" -const val SCAN_RESULT_KEY = "SCAN_RESULT" +val CameraOverlayButtonSize = 40.dp private const val TAG = "QrScanningScreen" @OptIn(ExperimentalPermissionsApi::class) @Composable fun QrScanningScreen( - navController: NavController, - inSheet: Boolean = false, - onBack: () -> Unit = { navController.popBackStack() }, + onBack: () -> Unit, onScanSuccess: (String) -> Unit, ) { val app = appViewModel ?: return @@ -100,20 +93,7 @@ fun QrScanningScreen( // Handle scan result LaunchedEffect(scanResult) { scanResult?.let { qrCode -> - delay(100) // wait to prevent navigation result race conditions - - val prev = navController.previousBackStackEntry - val wasCalledForResult = prev?.savedStateHandle?.contains(SCAN_REQUEST_KEY) == true - if (wasCalledForResult) { - prev.savedStateHandle[SCAN_RESULT_KEY] = qrCode - onBack() - prev.savedStateHandle.remove(SCAN_REQUEST_KEY) - } else { - onBack() - onScanSuccess(qrCode) - } - - // Reset scan result to allow new scans + onScanSuccess(qrCode) setScanResult(null) } } @@ -205,7 +185,6 @@ fun QrScanningScreen( deniedContent = { DeniedContent( shouldShowRationale = cameraPermissionState.status.shouldShowRationale, - inSheet = inSheet, onClickOpenSettings = { context.startActivityAppSettings() }, @@ -217,14 +196,10 @@ fun QrScanningScreen( grantedContent = { Column( modifier = Modifier - .then(if (inSheet) Modifier.gradientBackground() else Modifier) - .then(if (inSheet) Modifier.navigationBarsPadding() else Modifier.systemBarsPadding()) + .gradientBackground() + .navigationBarsPadding() ) { - if (inSheet) { - SheetTopBar(stringResource(R.string.other__qr_scan), onBack = onBack) - } else { - AppTopBar(stringResource(R.string.other__qr_scan), onBackClick = onBack) - } + SheetTopBar(stringResource(R.string.other__qr_scan), onBack = onBack) Content( previewView = previewView, @@ -297,7 +272,7 @@ private fun Content( .padding(16.dp) .clip(CircleShape) .background(Colors.White64) - .size(48.dp) + .size(CameraOverlayButtonSize) .align(Alignment.TopStart) ) { Icon( @@ -313,7 +288,7 @@ private fun Content( .padding(16.dp) .clip(CircleShape) .background(Colors.White64) - .size(48.dp) + .size(CameraOverlayButtonSize) .align(Alignment.TopEnd) ) { Icon( diff --git a/app/src/main/java/to/bitkit/ui/screens/settings/ProbingToolScreen.kt b/app/src/main/java/to/bitkit/ui/screens/settings/ProbingToolScreen.kt index d3e2da661..0be52d4f0 100644 --- a/app/src/main/java/to/bitkit/ui/screens/settings/ProbingToolScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/settings/ProbingToolScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll 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 @@ -27,11 +26,10 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController -import kotlinx.coroutines.flow.filterNotNull import to.bitkit.R +import to.bitkit.ui.appViewModel import to.bitkit.ui.components.ButtonSize import to.bitkit.ui.components.PrimaryButton import to.bitkit.ui.components.SecondaryButton @@ -40,11 +38,9 @@ import to.bitkit.ui.components.VerticalSpacer import to.bitkit.ui.components.settings.SectionFooter import to.bitkit.ui.components.settings.SectionHeader import to.bitkit.ui.components.settings.SettingsTextButtonRow -import to.bitkit.ui.navigateToScanner import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.ScanNavIcon import to.bitkit.ui.scaffold.ScreenColumn -import to.bitkit.ui.screens.scanner.SCAN_RESULT_KEY import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import to.bitkit.viewmodels.ProbeResult @@ -53,25 +49,20 @@ import to.bitkit.viewmodels.ProbingToolViewModel @Composable fun ProbingToolScreen( - savedStateHandle: SavedStateHandle, navController: NavController, viewModel: ProbingToolViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - - LaunchedEffect(savedStateHandle) { - savedStateHandle.getStateFlow(SCAN_RESULT_KEY, null) - .filterNotNull() - .collect { scannedData -> - viewModel.updateInvoice(scannedData) - savedStateHandle.remove(SCAN_RESULT_KEY) - } - } + val app = appViewModel ?: return ProbingToolContent( uiState = uiState, onBackClick = { navController.popBackStack() }, - onScanClick = { navController.navigateToScanner(isCalledForResult = true) }, + onScanClick = { + app.showScannerSheet { + viewModel.updateInvoice(it) + } + }, onInvoiceChange = viewModel::updateInvoice, onAmountChange = viewModel::updateAmountSats, onPasteInvoice = viewModel::pasteInvoice, diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt index 2fe68d868..2b040071f 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt @@ -31,8 +31,6 @@ import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.lifecycle.SavedStateHandle -import kotlinx.coroutines.flow.filterNotNull import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.R import to.bitkit.ext.getClipboardText @@ -50,7 +48,6 @@ import to.bitkit.ui.components.TextInput import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.DrawerNavIcon import to.bitkit.ui.scaffold.ScreenColumn -import to.bitkit.ui.screens.scanner.SCAN_RESULT_KEY import to.bitkit.ui.screens.transfer.external.ExternalNodeContract.SideEffect import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors @@ -59,7 +56,6 @@ import to.bitkit.ui.utils.withAccent @Composable fun ExternalConnectionScreen( route: Routes.ExternalConnection, - savedStateHandle: SavedStateHandle, viewModel: ExternalNodeViewModel, onNodeConnected: () -> Unit, onScanClick: () -> Unit, @@ -75,16 +71,6 @@ fun ExternalConnectionScreen( } } - // Handle result from scanner opened from this screen - LaunchedEffect(savedStateHandle) { - savedStateHandle.getStateFlow(SCAN_RESULT_KEY, null) - .filterNotNull() - .collect { scannedData -> - viewModel.parseNodeUri(scannedData) - savedStateHandle.remove(SCAN_RESULT_KEY) - } - } - LaunchedEffect(viewModel, onNodeConnected) { viewModel.effects.collect { when (it) { diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendRecipientScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendRecipientScreen.kt index c6837c539..04739567c 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendRecipientScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendRecipientScreen.kt @@ -69,6 +69,7 @@ import to.bitkit.ui.components.PrimaryButton import to.bitkit.ui.components.RectangleButton import to.bitkit.ui.components.VerticalSpacer import to.bitkit.ui.scaffold.SheetTopBar +import to.bitkit.ui.screens.scanner.CameraOverlayButtonSize import to.bitkit.ui.screens.scanner.QrCodeAnalyzer import to.bitkit.ui.shared.modifiers.sheetHeight import to.bitkit.ui.shared.util.gradientBackground @@ -372,7 +373,7 @@ private fun CameraPreviewWithControls( .padding(16.dp) .clip(CircleShape) .background(Colors.White64) - .size(48.dp) + .size(CameraOverlayButtonSize) .align(Alignment.TopStart) ) { Icon( @@ -397,7 +398,7 @@ private fun CameraPreviewWithControls( .padding(16.dp) .clip(CircleShape) .background(Colors.White64) - .size(48.dp) + .size(CameraOverlayButtonSize) .align(Alignment.TopEnd) ) { Icon( diff --git a/app/src/main/java/to/bitkit/ui/settings/advanced/ElectrumConfigScreen.kt b/app/src/main/java/to/bitkit/ui/settings/advanced/ElectrumConfigScreen.kt index 72531e42f..1fb2e584f 100644 --- a/app/src/main/java/to/bitkit/ui/settings/advanced/ElectrumConfigScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/advanced/ElectrumConfigScreen.kt @@ -24,10 +24,8 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController -import kotlinx.coroutines.flow.filterNotNull import to.bitkit.R import to.bitkit.models.ElectrumProtocol import to.bitkit.models.ElectrumServerPeer @@ -42,17 +40,14 @@ import to.bitkit.ui.components.TextInput import to.bitkit.ui.components.VerticalSpacer import to.bitkit.ui.components.settings.SettingsButtonRow import to.bitkit.ui.components.settings.SettingsButtonValue -import to.bitkit.ui.navigateToScanner import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.ScanNavIcon import to.bitkit.ui.scaffold.ScreenColumn -import to.bitkit.ui.screens.scanner.SCAN_RESULT_KEY import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors @Composable fun ElectrumConfigScreen( - savedStateHandle: SavedStateHandle, navController: NavController, viewModel: ElectrumConfigViewModel = hiltViewModel(), ) { @@ -60,16 +55,6 @@ fun ElectrumConfigScreen( val app = appViewModel ?: return val context = LocalContext.current - // Handle result from Scanner - LaunchedEffect(savedStateHandle) { - savedStateHandle.getStateFlow(SCAN_RESULT_KEY, null) - .filterNotNull() - .collect { scannedData -> - viewModel.onScan(scannedData) - savedStateHandle.remove(SCAN_RESULT_KEY) - } - } - // Monitor connection results LaunchedEffect(uiState.connectionResult) { uiState.connectionResult?.let { result -> @@ -97,7 +82,11 @@ fun ElectrumConfigScreen( Content( uiState = uiState, onBack = { navController.popBackStack() }, - onScan = { navController.navigateToScanner(isCalledForResult = true) }, + onScan = { + app.showScannerSheet { + viewModel.onScan(it) + } + }, onChangeHost = viewModel::setHost, onChangePort = viewModel::setPort, onChangeProtocol = viewModel::setProtocol, diff --git a/app/src/main/java/to/bitkit/ui/settings/advanced/RgsServerScreen.kt b/app/src/main/java/to/bitkit/ui/settings/advanced/RgsServerScreen.kt index cf74847db..c6685c6dc 100644 --- a/app/src/main/java/to/bitkit/ui/settings/advanced/RgsServerScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/advanced/RgsServerScreen.kt @@ -21,10 +21,8 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController -import kotlinx.coroutines.flow.filterNotNull import to.bitkit.R import to.bitkit.models.Toast import to.bitkit.ui.appViewModel @@ -35,17 +33,14 @@ import to.bitkit.ui.components.PrimaryButton import to.bitkit.ui.components.SecondaryButton import to.bitkit.ui.components.TextInput import to.bitkit.ui.components.VerticalSpacer -import to.bitkit.ui.navigateToScanner import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.ScanNavIcon import to.bitkit.ui.scaffold.ScreenColumn -import to.bitkit.ui.screens.scanner.SCAN_RESULT_KEY import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors @Composable fun RgsServerScreen( - savedStateHandle: SavedStateHandle, navController: NavController, viewModel: RgsServerViewModel = hiltViewModel(), ) { @@ -53,16 +48,6 @@ fun RgsServerScreen( val app = appViewModel ?: return val context = LocalContext.current - // Handle result from Scanner - LaunchedEffect(savedStateHandle) { - savedStateHandle.getStateFlow(SCAN_RESULT_KEY, null) - .filterNotNull() - .collect { scannedData -> - viewModel.onScan(scannedData) - savedStateHandle.remove(SCAN_RESULT_KEY) - } - } - // Monitor connection results LaunchedEffect(uiState.connectionResult) { uiState.connectionResult?.let { result -> @@ -88,7 +73,11 @@ fun RgsServerScreen( Content( uiState = uiState, onBack = { navController.popBackStack() }, - onScan = { navController.navigateToScanner(isCalledForResult = true) }, + onScan = { + app.showScannerSheet { + viewModel.onScan(it) + } + }, onChangeUrl = viewModel::setRgsUrl, onClickReset = viewModel::resetToDefault, onClickConnect = viewModel::onClickConnect, diff --git a/app/src/main/java/to/bitkit/ui/sheets/QrScanningSheet.kt b/app/src/main/java/to/bitkit/ui/sheets/QrScanningSheet.kt new file mode 100644 index 000000000..48d3e2aa4 --- /dev/null +++ b/app/src/main/java/to/bitkit/ui/sheets/QrScanningSheet.kt @@ -0,0 +1,34 @@ +package to.bitkit.ui.sheets + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import to.bitkit.ui.screens.scanner.QrScanningScreen +import to.bitkit.ui.shared.modifiers.sheetHeight +import to.bitkit.viewmodels.AppViewModel + +@Composable +fun QrScanningSheet(appViewModel: AppViewModel) { + Content( + onBack = { appViewModel.hideSheet() }, + onScanSuccess = { appViewModel.onScannerSheetResult(it) }, + ) +} + +@Composable +private fun Content( + onBack: () -> Unit, + onScanSuccess: (String) -> Unit, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .sheetHeight() + ) { + QrScanningScreen( + onBack = onBack, + onScanSuccess = onScanSuccess, + ) + } +} diff --git a/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt b/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt index 5af5e4449..6397c904d 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt @@ -133,12 +133,12 @@ fun SendSheet( } composableWithDefaultTransitions { QrScanningScreen( - navController = navController, - inSheet = true, - ) { qrCode -> - navController.popBackStack() - appViewModel.onScanResult(data = qrCode) - } + onBack = { navController.popBackStack() }, + onScanSuccess = { + navController.popBackStack() + appViewModel.onScanResult(data = it) + }, + ) } composableWithDefaultTransitions { val sendUiState by appViewModel.sendUiState.collectAsStateWithLifecycle() diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index 2fdc4fc85..7f921db4d 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -2097,6 +2097,24 @@ class AppViewModel @Inject constructor( // endregion // region Sheets + private var scanResultHandler: ((String) -> Unit)? = null + + fun showScannerSheet(onResult: ((String) -> Unit)? = null) { + scanResultHandler = onResult + showSheet(Sheet.QrScanner) + } + + fun onScannerSheetResult(data: String) { + val handler = scanResultHandler + scanResultHandler = null + hideSheet() + if (handler != null) { + handler(data) + } else { + onScanResult(data) + } + } + fun showSheet(sheetType: Sheet) { viewModelScope.launch { _currentSheet.value?.let { @@ -2108,6 +2126,7 @@ class AppViewModel @Inject constructor( } fun hideSheet() { + scanResultHandler = null when { currentSheet.value is Sheet.TimedSheet -> { // Only dismiss if manager still has a sheet (user initiated)