fix ios transfer song bug

This commit is contained in:
2026-10-03 15:20:50 +08:00
parent e3ce4aa9fd
commit 34842e2577
24 changed files with 415 additions and 102 deletions
@@ -280,6 +280,17 @@ object AppContainer {
_libraryRevision.value++
}
/** 清空曲库元数据并立即通知仍在组合中的首页列表重新查询。 */
fun clearSongData() {
if (!isInitialized) return
settings.dataVersion = ""
library.clearMusic()
library.clearAlbums()
library.clearArtists()
refreshCarPlayCatalog()
_libraryRevision.value++
}
/** 清空喜欢、历史、歌单和播放队列,并通知首页刷新。 */
fun clearUserData() {
if (!isInitialized) return
@@ -536,7 +536,10 @@ private fun LandscapePlayerBody(
contentAlignment = Alignment.Center,
) {
BoxWithConstraints(Modifier.fillMaxSize()) {
val side = maxWidth.coerceAtMost(maxHeight).coerceAtLeast(1.dp)
val side = maxWidth
.coerceAtMost(maxHeight)
.coerceAtMost(300.dp)
.coerceAtLeast(1.dp)
PlayerCoverArt(music = current, size = side)
}
}
@@ -71,7 +71,6 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.jetbrains.compose.resources.ExperimentalResourceApi
@@ -334,10 +333,7 @@ fun SettingsScreen(
onClearSongs = {
scope.launch {
loadingMsg = I18n.t("resetting")
AppContainer.library.clearMusic()
AppContainer.library.clearAlbums()
AppContainer.library.clearArtists()
settings.dataVersion = ""
AppContainer.clearSongData()
loadingMsg = null
PlatformUi.showToast(I18n.t("clean_success"))
}
@@ -470,6 +466,7 @@ fun TransferScreen(onBack: () -> Unit, onOpenScan: () -> Unit) {
var coverAnimationsIdle by remember { mutableStateOf(true) }
var displayedSong by remember { mutableStateOf(state.current) }
var displayedArtist by remember { mutableStateOf(state.artist) }
LaunchedEffect(Unit) { PlatformUi.requestLocalNetworkPermission() }
KeepScreenOn()
var wasCompleted by remember { mutableStateOf(state.completed) }
LaunchedEffect(state.completed) {
@@ -594,9 +591,11 @@ private fun TransferCoverBlock(
onIdleChange: (Boolean) -> Unit,
onDisplayedSongChange: (String, String) -> Unit,
) {
val initialCover = remember { TransferCoverPage(coverKey, coverUrl, song, artist) }
val initialCover = remember {
TransferCoverPage(coverKey, coverUrl, song, artist, pageId = 0)
}
val covers = remember { mutableStateListOf(initialCover) }
val readyCoverKeys = remember { mutableStateListOf<String>() }
val readyCoverPages = remember { mutableStateListOf<Int>() }
val coverUpdates = remember { Channel<TransferCoverPage>(Channel.UNLIMITED) }
val pagerState = rememberPagerState(pageCount = { covers.size })
val latestOnIdleChange by rememberUpdatedState(onIdleChange)
@@ -615,20 +614,19 @@ private fun TransferCoverBlock(
val lastIndex = covers.lastIndex
if (covers[lastIndex].key == nextCover.key) {
// 同一封面只更新网络/本地地址,不改变 Pager 页码。
if (covers[lastIndex] != nextCover) covers[lastIndex] = nextCover
val updatedCover = nextCover.copy(pageId = covers[lastIndex].pageId)
if (covers[lastIndex] != updatedCover) covers[lastIndex] = updatedCover
latestOnDisplayedSongChange(nextCover.song, nextCover.artist)
continue
}
covers.add(nextCover)
val targetCover = nextCover.copy(pageId = covers.size)
covers.add(targetCover)
val targetPage = covers.lastIndex
snapshotFlow { pagerState.pageCount }.first { it > targetPage }
// 右侧页图片准备好后再 post 到下一帧启动滚动,避免空 Painter 滑到中央闪白。
withTimeoutOrNull(2_000.milliseconds) {
snapshotFlow {
nextCover.key.isBlank() || nextCover.key in readyCoverKeys
}.first { it }
}
// 每个新页面都等自己的图片首帧准备完成;不能复用相同封面 key 的旧完成状态,
// 也不能超时后强行切换,否则空 Painter 会在滑到中央时闪一下。
snapshotFlow { targetCover.pageId in readyCoverPages }.first { it }
delay(32.milliseconds)
runCatching { pagerState.animateScrollToPage(targetPage) }
latestOnDisplayedSongChange(nextCover.song, nextCover.artist)
@@ -652,8 +650,8 @@ private fun TransferCoverBlock(
TransferCoverCircle(
cover = cover,
onReady = {
if (cover.key.isNotBlank() && cover.key !in readyCoverKeys) {
readyCoverKeys.add(cover.key)
if (cover.pageId !in readyCoverPages) {
readyCoverPages.add(cover.pageId)
}
},
)
@@ -665,6 +663,7 @@ private data class TransferCoverPage(
val url: String,
val song: String,
val artist: String,
val pageId: Int = -1,
)
@OptIn(ExperimentalResourceApi::class)
@@ -776,6 +775,7 @@ fun DataSyncScreen(onBack: () -> Unit, onOpenScan: () -> Unit) {
val dark = LocalDarkTheme.current
val bg = if (dark) ColorMs.NightPrimary else ColorMs.LightPrimary
val connected = state.connected
LaunchedEffect(Unit) { PlatformUi.requestLocalNetworkPermission() }
KeepScreenOn()
Scaffold(
containerColor = bg,