Skip to content

Commit bf586cc

Browse files
committed
feat(player): Add support for deleting external subtitles
1 parent ffdd52c commit bf586cc

File tree

5 files changed

+167
-42
lines changed

5 files changed

+167
-42
lines changed

composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/ui/component/player/SubtitleControlFlyout.kt

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ import kotlinx.coroutines.Job
6464
import kotlinx.coroutines.delay
6565
import kotlinx.coroutines.launch
6666

67+
import com.jankinwu.fntv.client.icons.Delete
68+
6769
private val FlyoutBackgroundColor = Color.Black.copy(alpha = 0.9f)
6870
private val FlyoutBorderColor = Color.Gray.copy(alpha = 0.5f)
6971
private val SelectedTextColor = Color(0xFF2073DF)
@@ -84,7 +86,8 @@ fun SubtitleControlFlyout(
8486
onOpenAddNasSubtitle: () -> Unit,
8587
onOpenAddLocalSubtitle: () -> Unit,
8688
modifier: Modifier = Modifier,
87-
onHoverStateChanged: ((Boolean) -> Unit)? = null
89+
onHoverStateChanged: ((Boolean) -> Unit)? = null,
90+
onRequestDelete: ((SubtitleStream) -> Unit)? = null
8891
) {
8992
var isExpanded by remember { mutableStateOf(false) }
9093
val coroutineScope = rememberCoroutineScope()
@@ -99,6 +102,8 @@ fun SubtitleControlFlyout(
99102
hideJob?.cancel()
100103
isExpanded = true
101104
showPopup = true
105+
isAddMenuHovered = false
106+
popupHovered = false
102107
onHoverStateChanged?.invoke(true)
103108
}
104109

@@ -198,7 +203,12 @@ fun SubtitleControlFlyout(
198203
} else {
199204
hideFlyoutWithDelay()
200205
}
201-
}
206+
},
207+
onRequestDelete = { subtitle ->
208+
onRequestDelete?.invoke(subtitle)
209+
isExpanded = false
210+
},
211+
isExpanded = isExpanded
202212
)
203213
}
204214
}
@@ -256,7 +266,9 @@ fun SubtitleFlyoutContent(
256266
onOpenSubtitleSearch: () -> Unit,
257267
onOpenAddNasSubtitle: () -> Unit,
258268
onOpenAddLocalSubtitle: () -> Unit,
259-
onAddMenuHoverChanged: (Boolean) -> Unit
269+
onAddMenuHoverChanged: (Boolean) -> Unit,
270+
onRequestDelete: (SubtitleStream) -> Unit,
271+
isExpanded: Boolean = false
260272
) {
261273
val currentSubtitle = playingInfoCache?.currentSubtitleStream
262274
val subtitleList = playingInfoCache?.currentSubtitleStreamList ?: emptyList()
@@ -339,8 +351,18 @@ fun SubtitleFlyoutContent(
339351
modifier = Modifier.padding(vertical = 12.dp),
340352
color = Color.White.copy(alpha = 0.1f)
341353
)
342-
343354
val lazyListState = rememberLazyListState()
355+
LaunchedEffect(isExpanded) {
356+
if (isExpanded) {
357+
val index = subtitleList.indexOfFirst { it.guid == currentSubtitle?.guid }
358+
if (index != -1) {
359+
// 加1是因为有一个"关闭"选项在列表头部
360+
lazyListState.scrollToItem(index + 1)
361+
} else if (currentSubtitle == null) {
362+
lazyListState.scrollToItem(0)
363+
}
364+
}
365+
}
344366
AnimatedScrollbarLazyColumn(
345367
listState = lazyListState,
346368
modifier = Modifier.height(300.dp),
@@ -375,7 +397,9 @@ fun SubtitleFlyoutContent(
375397
title = "",
376398
isDefault = subtitle.isDefault == 1,
377399
isSelected = isSelected,
378-
onClick = { onSubtitleSelected(subtitle) }
400+
onClick = { onSubtitleSelected(subtitle) },
401+
isExternal = subtitle.isExternal == 1,
402+
onDelete = { onRequestDelete(subtitle) }
379403
)
380404
}
381405
}
@@ -482,7 +506,9 @@ fun SubtitleOptionItem(
482506
title: String,
483507
isDefault: Boolean,
484508
isSelected: Boolean,
485-
onClick: () -> Unit
509+
onClick: () -> Unit,
510+
isExternal: Boolean = false,
511+
onDelete: (() -> Unit)? = null
486512
) {
487513
val textColor = if (isSelected) SelectedTextColor else DefaultTextColor
488514
var isHovered by remember { mutableStateOf(false) }
@@ -529,8 +555,25 @@ fun SubtitleOptionItem(
529555
}
530556
}
531557

532-
// No checkmark in the screenshot for subtitle list, just blue text.
533-
// But QualityControlFlyout uses checkmark. The screenshot shows blue text and highlighted background.
534-
// I will keep it simple as per screenshot.
558+
if (isExternal && isHovered) {
559+
var isIconHovered by remember { mutableStateOf(false) }
560+
Box(
561+
modifier = Modifier
562+
.size(28.dp)
563+
.clip(RoundedCornerShape(50))
564+
.background(if (isIconHovered) HoverBackgroundColor else Color.Transparent)
565+
.clickable { onDelete?.invoke() }
566+
.onPointerEvent(PointerEventType.Enter) { isIconHovered = true }
567+
.onPointerEvent(PointerEventType.Exit) { isIconHovered = false },
568+
contentAlignment = Alignment.Center
569+
) {
570+
Icon(
571+
imageVector = Delete,
572+
contentDescription = "删除字幕",
573+
tint = DefaultTextColor,
574+
modifier = Modifier.size(14.dp)
575+
)
576+
}
577+
}
535578
}
536579
}

0 commit comments

Comments
 (0)