Straw phase I: SB segment count chip + clear-history buttons
Detail screen: VideoDetailViewModel now also fetches SponsorBlock segment count for the user's currently-enabled categories alongside RYD. When >0, detail screen shows a "⏭ N skip(s)" AssistChip next to the like/dislike chips. Lets the user see at-a-glance whether SB is going to do anything on this video before tapping Play. Settings screen: "History" section at the bottom with two OutlinedButtons — "Clear watch history" and "Clear searches". Each calls the corresponding HistoryStore.clear* method. List updates immediately via the StateFlow. Empty-category set on SB now means "skip the API call" (was already checking this in PlayerViewModel.resolve, now also in VideoDetailViewModel).
This commit is contained in:
parent
ce3ba9afa2
commit
6f5e1ed199
3 changed files with 32 additions and 0 deletions
|
|
@ -115,6 +115,12 @@ fun VideoDetailScreen(
|
|||
),
|
||||
)
|
||||
}
|
||||
if (d.sbSegmentCount > 0) {
|
||||
AssistChip(
|
||||
onClick = {},
|
||||
label = { Text("⏭ ${d.sbSegmentCount} skip${if (d.sbSegmentCount == 1) "" else "s"}") },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ package com.sulkta.straw.feature.detail
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.sulkta.straw.data.History
|
||||
import com.sulkta.straw.data.Settings
|
||||
import com.sulkta.straw.data.WatchHistoryItem
|
||||
import com.sulkta.straw.net.RydClient
|
||||
import com.sulkta.straw.net.RydVotes
|
||||
import com.sulkta.straw.net.SponsorBlockClient
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -27,6 +29,7 @@ data class VideoDetail(
|
|||
val description: String,
|
||||
val thumbnail: String?,
|
||||
val ryd: RydVotes? = null,
|
||||
val sbSegmentCount: Int = 0,
|
||||
)
|
||||
|
||||
data class VideoDetailUiState(
|
||||
|
|
@ -70,6 +73,10 @@ class VideoDetailViewModel : ViewModel() {
|
|||
val ryd = withContext(Dispatchers.IO) {
|
||||
runCatching { RydClient.fetch(videoId) }.getOrNull()
|
||||
}
|
||||
val sbCats = Settings.get().sbCategories.value.map { it.key }
|
||||
val sbCount = if (sbCats.isEmpty()) 0 else withContext(Dispatchers.IO) {
|
||||
runCatching { SponsorBlockClient.fetch(videoId, sbCats).size }.getOrDefault(0)
|
||||
}
|
||||
_ui.value = VideoDetailUiState(
|
||||
loading = false,
|
||||
detail = VideoDetail(
|
||||
|
|
@ -80,6 +87,7 @@ class VideoDetailViewModel : ViewModel() {
|
|||
description = info.description?.content ?: "",
|
||||
thumbnail = thumb,
|
||||
ryd = ryd,
|
||||
sbSegmentCount = sbCount,
|
||||
),
|
||||
streamInfo = info,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import androidx.compose.foundation.rememberScrollState
|
|||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -26,6 +27,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.sulkta.straw.data.History
|
||||
import com.sulkta.straw.data.SbCategory
|
||||
import com.sulkta.straw.data.Settings
|
||||
|
||||
|
|
@ -68,6 +70,22 @@ fun SettingsScreen() {
|
|||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
Text(
|
||||
"History",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
OutlinedButton(onClick = { History.get().clearWatches() }) {
|
||||
Text("Clear watch history")
|
||||
}
|
||||
OutlinedButton(onClick = { History.get().clearSearches() }) {
|
||||
Text("Clear searches")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue