Skip to content
Merged
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
24 changes: 17 additions & 7 deletions app/src/main/java/to/bitkit/ui/ContentView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,21 @@ fun ContentView(
val context = LocalContext.current
val lifecycle = LocalLifecycleOwner.current.lifecycle

val walletUiState by walletViewModel.walletState.collectAsStateWithLifecycle()
val lightningState by walletViewModel.lightningState.collectAsStateWithLifecycle()
val nodeLifecycleState = lightningState.nodeLifecycleState

val isRecoveryMode by walletViewModel.isRecoveryMode.collectAsStateWithLifecycle()
val notificationsGranted by settingsViewModel.notificationsGranted.collectAsStateWithLifecycle()
val walletExists = walletUiState.walletExists

// Effects on app entering fg (ON_START) / bg (ON_STOP)
DisposableEffect(lifecycle) {
// TODO ADAPT THIS LOGIC TO WORK WITH LightningNodeService
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_START -> {
try {
if (walletExists && !isRecoveryMode) {
walletViewModel.start()
} catch (e: Throwable) {
Logger.error("Failed to start wallet", e)
}

val pendingTransaction = NewTransactionSheetDetails.load(context)
Expand All @@ -208,6 +213,14 @@ fun ContentView(
blocktankViewModel.refreshOrders()
}

Lifecycle.Event.ON_STOP -> {
if (walletExists && !isRecoveryMode && !notificationsGranted) {
// App backgrounded without notification permission - stop node
walletViewModel.stop()
}
// If notificationsGranted=true, service keeps node running
}

else -> Unit
}
}
Expand Down Expand Up @@ -242,9 +255,6 @@ fun ContentView(
}
}

val walletUiState by walletViewModel.uiState.collectAsStateWithLifecycle()
val nodeLifecycleState = walletUiState.nodeLifecycleState

var walletIsInitializing by remember { mutableStateOf(nodeLifecycleState == NodeLifecycleState.Initializing) }
var walletInitShouldFinish by remember { mutableStateOf(false) }

Expand Down
40 changes: 39 additions & 1 deletion app/src/main/java/to/bitkit/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import to.bitkit.androidServices.LightningNodeService
Expand All @@ -45,6 +46,7 @@ import to.bitkit.ui.sheets.NewTransactionSheet
import to.bitkit.ui.theme.AppThemeSurface
import to.bitkit.ui.utils.composableWithDefaultTransitions
import to.bitkit.ui.utils.enableAppEdgeToEdge
import to.bitkit.utils.Logger
import to.bitkit.viewmodels.ActivityListViewModel
import to.bitkit.viewmodels.AppViewModel
import to.bitkit.viewmodels.BackupsViewModel
Expand Down Expand Up @@ -78,7 +80,7 @@ class MainActivity : FragmentActivity() {
importance = NotificationManager.IMPORTANCE_LOW
)
appViewModel.handleDeeplinkIntent(intent)
startForegroundService(Intent(this, LightningNodeService::class.java))

installSplashScreen()
enableAppEdgeToEdge()
setContent {
Expand All @@ -89,6 +91,21 @@ class MainActivity : FragmentActivity() {
) {
val scope = rememberCoroutineScope()
val isRecoveryMode by walletViewModel.isRecoveryMode.collectAsStateWithLifecycle()
val notificationsGranted by settingsViewModel.notificationsGranted.collectAsStateWithLifecycle()
val walletExists by walletViewModel.walletState
.map { it.walletExists }
.collectAsStateWithLifecycle(initialValue = walletViewModel.walletExists)

LaunchedEffect(
walletExists,
isRecoveryMode,
notificationsGranted
) {
if (walletExists && !isRecoveryMode && notificationsGranted) {
tryStartForegroundService()
}
}

if (!walletViewModel.walletExists && !isRecoveryMode) {
OnboardingNav(
startupNavController = rememberNavController(),
Expand Down Expand Up @@ -170,6 +187,27 @@ class MainActivity : FragmentActivity() {
setIntent(intent)
appViewModel.handleDeeplinkIntent(intent)
}

override fun onDestroy() {
super.onDestroy()
if (!settingsViewModel.notificationsGranted.value) {
runCatching {
stopService(Intent(this, LightningNodeService::class.java))
}
}
}

/**
* Attempts to start the LightningNodeService if it's not already running.
*/
private fun tryStartForegroundService() {
runCatching {
Logger.debug("Attempting to start LightningNodeService", context = "MainActivity")
startForegroundService(Intent(this, LightningNodeService::class.java))
}.onFailure { error ->
Logger.error("Failed to start LightningNodeService", error, context = "MainActivity")
}
}
}

@Composable
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,18 @@ class WalletViewModel @Inject constructor(
}
}

fun stop() {
if (!walletExists) return

viewModelScope.launch(bgDispatcher) {
lightningRepo.stop()
.onFailure { error ->
Logger.error("Node stop error", error)
ToastEventBus.send(error)
}
}
}

suspend fun observeLdkWallet() {
walletRepo.observeLdkWallet()
}
Expand Down
Loading