Fixed unfavorite list jump

This commit is contained in:
OmniaX-Dev 2026-06-23 11:39:25 +02:00
parent 02dd3c154a
commit 8baa347e81
2 changed files with 23 additions and 3 deletions

View file

@ -4,10 +4,10 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-06-23T09:15:42.913635127Z"> <DropdownSelection timestamp="2026-06-23T09:36:00.583173984Z">
<Target type="DEFAULT_BOOT"> <Target type="DEFAULT_BOOT">
<handle> <handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=RFCY20YA30P" /> <DeviceId pluginId="LocalEmulator" identifier="path=/home/sylar/.android/avd/Medium_Phone.avd" />
</handle> </handle>
</Target> </Target>
</DropdownSelection> </DropdownSelection>

View file

@ -45,8 +45,10 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.runtime.withFrameNanos
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
@ -56,6 +58,8 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.keylightpiano.pianotimeline.R import com.keylightpiano.pianotimeline.R
import kotlinx.coroutines.launch
import com.keylightpiano.pianotimeline.domain.Recording
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@Composable @Composable
@ -93,6 +97,22 @@ fun RecordingListScreen(
wasRefreshing = isRefreshing wasRefreshing = isRefreshing
} }
// Preserve scroll position across a favorite toggle (which reorders the list).
// When the user stars/unstars an item, we snapshot the current top item's
// index+offset, then restore it after the list settles so the viewport
// doesn't jump to follow the moved item.
val coroutineScope = rememberCoroutineScope()
val onFavoriteToggle: (Recording) -> Unit = { recording ->
val anchorIndex = listState.firstVisibleItemIndex
val anchorOffset = listState.firstVisibleItemScrollOffset
vm.toggleFavorite(recording)
coroutineScope.launch {
// Wait one frame for the reordered list to be applied, then restore.
withFrameNanos { }
listState.scrollToItem(anchorIndex, anchorOffset)
}
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val hasActiveFilter = searchQuery.isNotEmpty() || hiddenArtists.isNotEmpty() val hasActiveFilter = searchQuery.isNotEmpty() || hiddenArtists.isNotEmpty()
@ -269,7 +289,7 @@ fun RecordingListScreen(
RecordingItem( RecordingItem(
recording = recording, recording = recording,
onPlayClick = { vm.onPlay(recording) }, onPlayClick = { vm.onPlay(recording) },
onFavoriteClick = { vm.toggleFavorite(recording) }, onFavoriteClick = { onFavoriteToggle(recording) },
onNotesClick = if (recording.hasMidi) { onNotesClick = if (recording.hasMidi) {
{ /* TODO: open falling notes */ } { /* TODO: open falling notes */ }
} else null } else null