Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 12 additions & 39 deletions app/src/main/java/to/bitkit/ui/ContentView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 -> {
Expand Down Expand Up @@ -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)
)
}
Expand Down Expand Up @@ -542,7 +540,6 @@ private fun RootNavHost(
cjitDetailSettings(navController)
lightningConnections(navController)
activityItem(activityListViewModel, navController)
qrScanner(appViewModel, navController)
authCheck(navController)
logs(navController)
suggestions(navController)
Expand Down Expand Up @@ -684,7 +681,7 @@ private fun RootNavHost(
}
composableWithDefaultTransitions<Routes.FundingAdvanced> {
FundingAdvancedScreen(
onLnurl = { navController.navigateToScanner() },
onLnurl = { appViewModel.showScannerSheet() },
onManual = { navController.navigate(Routes.ExternalNav) },
onBackClick = { navController.popBackStack() },
)
Expand All @@ -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() },
)
}
Expand Down Expand Up @@ -880,7 +880,7 @@ private fun NavGraphBuilder.settings(
VssDebugScreen(navController)
}
composableWithDefaultTransitions<Routes.ProbingTool> {
ProbingToolScreen(it.savedStateHandle, navController)
ProbingToolScreen(navController)
}
composableWithDefaultTransitions<Routes.FeeSettings> {
FeeSettingsScreen(navController)
Expand Down Expand Up @@ -1005,10 +1005,10 @@ private fun NavGraphBuilder.advancedSettings(navController: NavHostController) {
CoinSelectPreferenceScreen(navController)
}
composableWithDefaultTransitions<Routes.ElectrumConfig> {
ElectrumConfigScreen(it.savedStateHandle, navController)
ElectrumConfigScreen(navController)
}
composableWithDefaultTransitions<Routes.RgsServer> {
RgsServerScreen(it.savedStateHandle, navController)
RgsServerScreen(navController)
}
composableWithDefaultTransitions<Routes.AddressTypePreference> {
AddressTypePreferenceScreen(navController)
Expand Down Expand Up @@ -1200,23 +1200,6 @@ private fun NavGraphBuilder.activityItem(
}
}

private fun NavGraphBuilder.qrScanner(
appViewModel: AppViewModel,
navController: NavHostController,
) {
composableWithDefaultTransitions<Routes.QrScanner>(
enterTransition = { Transitions.slideInVertically },
popExitTransition = { Transitions.slideOutVertically },
) {
QrScanningScreen(navController = navController) { qrCode ->
appViewModel.onScanResult(
data = qrCode,
delayMs = TRANSITION_SHEET_MS,
)
}
}
}

private fun NavGraphBuilder.authCheck(
navController: NavHostController,
) {
Expand Down Expand Up @@ -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),
)
Expand Down Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/to/bitkit/ui/components/SheetHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -62,22 +59,17 @@ fun CameraPermissionView(
@Composable
fun DeniedContent(
shouldShowRationale: Boolean,
inSheet: Boolean = false,
onClickOpenSettings: () -> Unit = {},
onClickRetry: () -> Unit = {},
onClickPaste: () -> Unit = {},
onBack: () -> Unit = {},
) {
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,
Expand Down Expand Up @@ -165,14 +157,3 @@ fun PreviewDenied() {
DeniedContent(shouldShowRationale = true)
}
}

@Preview(showSystemUi = true)
@Composable()
fun PreviewInSheet() {
AppThemeSurface {
DeniedContent(
shouldShowRationale = true,
inSheet = true,
)
}
}
41 changes: 8 additions & 33 deletions app/src/main/java/to/bitkit/ui/screens/scanner/QrScanningScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -72,25 +69,21 @@ 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
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
Expand All @@ -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<Boolean?>(SCAN_REQUEST_KEY)
} else {
onBack()
onScanSuccess(qrCode)
}

// Reset scan result to allow new scans
onScanSuccess(qrCode)
setScanResult(null)
}
}
Expand Down Expand Up @@ -205,7 +185,6 @@ fun QrScanningScreen(
deniedContent = {
DeniedContent(
shouldShowRationale = cameraPermissionState.status.shouldShowRationale,
inSheet = inSheet,
onClickOpenSettings = {
context.startActivityAppSettings()
},
Expand All @@ -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,
Expand Down Expand Up @@ -297,7 +272,7 @@ private fun Content(
.padding(16.dp)
.clip(CircleShape)
.background(Colors.White64)
.size(48.dp)
.size(CameraOverlayButtonSize)
.align(Alignment.TopStart)
) {
Icon(
Expand All @@ -313,7 +288,7 @@ private fun Content(
.padding(16.dp)
.clip(CircleShape)
.background(Colors.White64)
.size(48.dp)
.size(CameraOverlayButtonSize)
.align(Alignment.TopEnd)
) {
Icon(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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<String?>(SCAN_RESULT_KEY, null)
.filterNotNull()
.collect { scannedData ->
viewModel.updateInvoice(scannedData)
savedStateHandle.remove<String>(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,
Expand Down
Loading
Loading