@@ -28,12 +28,13 @@ import androidx.compose.material3.ExperimentalMaterial3Api
2828import androidx.compose.material3.Icon
2929import androidx.compose.material3.rememberTooltipState
3030import androidx.compose.runtime.Composable
31- import androidx.compose.runtime.derivedStateOf
31+ import androidx.compose.runtime.LaunchedEffect
3232import androidx.compose.runtime.getValue
3333import androidx.compose.runtime.mutableStateOf
3434import androidx.compose.runtime.remember
3535import androidx.compose.runtime.rememberCoroutineScope
3636import androidx.compose.runtime.setValue
37+ import androidx.compose.runtime.snapshotFlow
3738import androidx.compose.ui.Alignment
3839import androidx.compose.ui.Modifier
3940import androidx.compose.ui.draw.clip
@@ -48,6 +49,8 @@ import androidx.compose.ui.res.stringResource
4849import androidx.compose.ui.tooling.preview.Devices.NEXUS_5
4950import androidx.compose.ui.tooling.preview.Preview
5051import androidx.compose.ui.unit.dp
52+ import kotlinx.coroutines.FlowPreview
53+ import kotlinx.coroutines.flow.distinctUntilChanged
5154import kotlinx.coroutines.launch
5255import org.lightningdevkit.ldknode.ChannelDetails
5356import to.bitkit.R
@@ -77,6 +80,7 @@ import to.bitkit.ui.theme.Colors
7780import to.bitkit.ui.utils.withAccent
7881import to.bitkit.viewmodels.MainUiState
7982
83+ @OptIn(FlowPreview ::class )
8084@Composable
8185fun ReceiveQrScreen (
8286 cjitInvoice : String? ,
@@ -123,58 +127,39 @@ fun ReceiveQrScreen(
123127 }
124128 }
125129
126- // Determine initial tab index
127- val initialTabIndex = remember(initialTab, visibleTabs) {
128- if (initialTab != null ) {
129- visibleTabs.indexOf(initialTab).coerceAtLeast(0 )
130- } else {
131- when {
132- ! cjitInvoice.isNullOrEmpty() -> visibleTabs.indexOf(ReceiveTab .SPENDING )
133- hasUsableChannels -> visibleTabs.indexOf(ReceiveTab .AUTO )
134- else -> visibleTabs.indexOf(ReceiveTab .SAVINGS )
135- }.coerceAtLeast(0 )
136- }
137- }
138-
139130 // LazyRow state with snap behavior
140131 val scope = rememberCoroutineScope()
141- val lazyListState = rememberLazyListState(
142- initialFirstVisibleItemIndex = initialTabIndex
143- )
132+ val lazyListState = rememberLazyListState()
144133
145134 val snapBehavior = rememberSnapFlingBehavior(
146135 lazyListState = lazyListState,
147136 snapPosition = SnapPosition .Center
148137 )
149138
150139 // Calculate current tab based on scroll position for smooth indicator and color updates
151- val selectedTab by remember {
152- derivedStateOf {
153- val layoutInfo = lazyListState.layoutInfo
154- val currentIndex = if (layoutInfo.visibleItemsInfo.isEmpty()) {
155- lazyListState.firstVisibleItemIndex
156- } else {
157- val viewportMidpoint = layoutInfo.viewportStartOffset +
158- (layoutInfo.viewportEndOffset - layoutInfo.viewportStartOffset) / 2
159-
160- layoutInfo.visibleItemsInfo
161- .minByOrNull { item ->
162- val itemMidpoint = item.offset + item.size / 2
163- kotlin.math.abs(itemMidpoint - viewportMidpoint)
164- }
165- ?.index ? : lazyListState.firstVisibleItemIndex
166- }
140+ var selectedTab by remember {
141+ mutableStateOf(initialTab ? : ReceiveTab .SAVINGS )
142+ }
167143
168- visibleTabs.getOrNull(currentIndex)
169- ? : visibleTabs.firstOrNull()
170- ? : ReceiveTab .SAVINGS
171- }
144+ LaunchedEffect (lazyListState, visibleTabs.size) {
145+ snapshotFlow { lazyListState.firstVisibleItemIndex }
146+ .distinctUntilChanged()
147+ .collect { index ->
148+ if (index < visibleTabs.size && index > - 1 ) {
149+ val tab = visibleTabs[index]
150+ selectedTab = tab
151+ }
152+ }
172153 }
173154
174- // Derive index from selectedTab for tab row indicator
175- val currentTabIndex by remember {
176- derivedStateOf {
177- visibleTabs.indexOf(selectedTab).coerceAtLeast(0 )
155+ // Auto-switch to AUTO tab when it becomes available for the first time
156+ LaunchedEffect (hasUsableChannels) {
157+ if (hasUsableChannels && visibleTabs.contains(ReceiveTab .AUTO )) {
158+ val autoIndex = visibleTabs.indexOf(ReceiveTab .AUTO )
159+ if (autoIndex != - 1 ) {
160+ lazyListState.animateScrollToItem(autoIndex)
161+ selectedTab = ReceiveTab .AUTO
162+ }
178163 }
179164 }
180165
@@ -198,11 +183,12 @@ fun ReceiveQrScreen(
198183 // Tab row
199184 CustomTabRowWithSpacing (
200185 tabs = visibleTabs,
201- currentTabIndex = currentTabIndex ,
186+ currentTabIndex = visibleTabs.indexOf(selectedTab) ,
202187 selectedColor = selectedTab.accentColor,
203188 onTabChange = { tab ->
204189 haptic.performHapticFeedback(HapticFeedbackType .TextHandleMove )
205190 val newIndex = visibleTabs.indexOf(tab)
191+ selectedTab = tab
206192 scope.launch {
207193 lazyListState.animateScrollToItem(newIndex)
208194 }
@@ -303,12 +289,12 @@ fun ReceiveQrScreen(
303289 modifier = Modifier
304290 .padding(horizontal = 16 .dp)
305291 .testTag(
306- if (showDetails) {
307- " QRCode"
308- } else {
309- " ShowDetails"
310- }
311- )
292+ if (showDetails) {
293+ " QRCode"
294+ } else {
295+ " ShowDetails"
296+ }
297+ )
312298 )
313299 }
314300
0 commit comments