Skip to content

Commit

Permalink
Implement episode pane
Browse files Browse the repository at this point in the history
  • Loading branch information
Him188 committed Sep 22, 2024
1 parent 35115d7 commit a40a297
Show file tree
Hide file tree
Showing 23 changed files with 744 additions and 339 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,11 @@ abstract class SelectorMediaSourceEngine {

fun matchWebVideo(url: String, searchConfig: SelectorSearchConfig.MatchVideoConfig): WebVideo? {
val result = searchConfig.matchVideoUrlRegex?.find(url) ?: return null
val videoUrl = result.groups["v"]?.value ?: result.value
val videoUrl = try {
result.groups["v"]?.value ?: url
} catch (_: IllegalArgumentException) { // no group
url
}
return WebVideo(
videoUrl,
mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ data class SelectorSearchConfig(
@Serializable
data class MatchVideoConfig(
@Suppress("RegExpRedundantEscape")
val matchVideoUrl: String = """^(?<v>http(s)?:\/\/(?!.*http(s)?:\/\/).+((\.mp4)|(\.mkv)|(\.m3u8)))""",
val matchVideoUrl: String = """^(?<v>http(s)?:\/\/(?!.*http(s)?:\/\/).+((\.mp4)|(\.mkv)|(m3u8)).*(\?.+)?)""",
val addHeadersToVideo: VideoHeaders = VideoHeaders(),
) {
val matchVideoUrlRegex by lazy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import me.him188.ani.app.ui.settings.SettingsViewModel
import me.him188.ani.app.ui.settings.mediasource.rss.EditRssMediaSourcePage
import me.him188.ani.app.ui.settings.mediasource.rss.EditRssMediaSourceViewModel
import me.him188.ani.app.ui.settings.mediasource.selector.EditSelectorMediaSourcePage
import me.him188.ani.app.ui.settings.mediasource.selector.SelectorMediaSourceConfigurationViewModel
import me.him188.ani.app.ui.settings.mediasource.selector.EditSelectorMediaSourceViewModel
import me.him188.ani.app.ui.settings.tabs.media.torrent.peer.PeerFilterSettingsPage
import me.him188.ani.app.ui.settings.tabs.media.torrent.peer.PeerFilterSettingsViewModel
import me.him188.ani.app.ui.subject.cache.SubjectCacheScene
Expand Down Expand Up @@ -311,8 +311,8 @@ fun AniAppContentPortrait(
SelectorMediaSource.FactoryId -> {
val context = LocalContext.current
EditSelectorMediaSourcePage(
viewModel<SelectorMediaSourceConfigurationViewModel>(key = mediaSourceInstanceId) {
SelectorMediaSourceConfigurationViewModel(mediaSourceInstanceId, context)
viewModel<EditSelectorMediaSourceViewModel>(key = mediaSourceInstanceId) {
EditSelectorMediaSourceViewModel(mediaSourceInstanceId, context)
},
Modifier,
windowInsets = windowInsets,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import me.him188.ani.utils.platform.annotations.TestOnly
@TestOnly
fun rememberTestSelectorConfigurationState(
arguments: SelectorMediaSourceArguments = SelectorMediaSourceArguments.Default
): SelectorConfigurationState {
): SelectorConfigState {
return remember {
SelectorConfigurationState(
SelectorConfigState(
createTestSaveableStorage(
arguments,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fun PreviewSelectorConfigurationPane() = ProvideFoundationCompositionLocalsForPr
Surface {
SelectorConfigurationPane(
remember {
SelectorConfigurationState(
SelectorConfigState(
createTestSaveableStorage(
SelectorMediaSourceArguments.Default,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,61 +9,52 @@

package me.him188.ani.app.ui.settings.mediasource.selector.episode

import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.tooling.preview.Preview
import me.him188.ani.app.data.source.media.resolver.TestWebViewVideoExtractor
import me.him188.ani.app.data.source.media.source.web.SelectorMediaSourceArguments
import me.him188.ani.app.data.source.media.source.web.SelectorSearchConfig
import me.him188.ani.app.platform.LocalContext
import me.him188.ani.app.ui.foundation.ProvideFoundationCompositionLocalsForPreview
import me.him188.ani.app.ui.foundation.stateOf
import me.him188.ani.app.ui.settings.mediasource.rss.createTestSaveableStorage
import me.him188.ani.app.ui.settings.mediasource.rss.test.buildMatchTags
import me.him188.ani.app.ui.settings.mediasource.selector.edit.rememberTestSelectorConfigurationState
import me.him188.ani.app.ui.settings.mediasource.selector.EditSelectorMediaSourcePageState
import me.him188.ani.app.ui.settings.mediasource.selector.test.SelectorTestEpisodePresentation
import me.him188.ani.app.ui.settings.mediasource.selector.test.TestSelectorMediaSourceEngine
import me.him188.ani.datasources.api.EpisodeSort
import me.him188.ani.utils.platform.annotations.TestOnly
import kotlin.coroutines.EmptyCoroutineContext

@TestOnly
private val configurationContent: @Composable ColumnScope.(contentPadding: PaddingValues) -> Unit = { contentPadding ->
SelectorEpisodePaneDefaults.ConfigurationContent(
rememberTestSelectorConfigurationState(),
contentPadding = contentPadding,
)
}

@OptIn(TestOnly::class)
@Composable
@Preview
fun PreviewSelectorEpisodePaneWithBottomSheet() = ProvideFoundationCompositionLocalsForPreview {
fun PreviewSelectorEpisodePaneCompact() = ProvideFoundationCompositionLocalsForPreview {
Surface {
SelectorEpisodePane(
state = rememberTestSelectorEpisodeState(
SelectorTestAndEpisodePane(
state = rememberTestEditSelectorMediaSourceState(
TestSelectorTestEpisodePresentations[0],
SelectorSearchConfig.MatchVideoConfig(),
),
layout = SelectorEpisodePaneLayout.WithBottomSheet,
configurationContent = configurationContent,
layout = SelectorEpisodePaneLayout.Compact,
)
}
}

@OptIn(TestOnly::class)
@Composable
@Preview
fun PreviewSelectorEpisodePaneListOnly() {
@Preview(device = "spec:width=1280dp,height=800dp,dpi=240")
fun PreviewSelectorEpisodePaneExpanded() {
ProvideFoundationCompositionLocalsForPreview {
Surface {
SelectorEpisodePane(
state = rememberTestSelectorEpisodeState(),
layout = SelectorEpisodePaneLayout.ListOnly,
configurationContent = configurationContent,
SelectorTestAndEpisodePane(
state = rememberTestEditSelectorMediaSourceState(),
layout = SelectorEpisodePaneLayout.Expanded,
initialRoute = SelectorEpisodePaneRoutes.EPISODE,
)
}
}
Expand Down Expand Up @@ -117,3 +108,36 @@ internal fun rememberTestSelectorEpisodeState(
)
}
}

@TestOnly
@Composable
internal fun rememberTestEditSelectorMediaSourceState(
viewing: SelectorTestEpisodePresentation? = TestSelectorTestEpisodePresentations[0],
matchVideoConfig: SelectorSearchConfig.MatchVideoConfig = SelectorSearchConfig.MatchVideoConfig(),
urls: (pageUrl: String) -> List<String> = {
listOf("https://example.com/a.mkv")
},
): EditSelectorMediaSourcePageState {
val context = LocalContext.current
val scope = rememberCoroutineScope()
return remember {
EditSelectorMediaSourcePageState(
createTestSaveableStorage(
SelectorMediaSourceArguments.Default.run {
copy(
searchConfig = searchConfig.copy(matchVideo = matchVideoConfig),
)
},
),
engine = TestSelectorMediaSourceEngine(),
webViewVideoExtractor = stateOf(TestWebViewVideoExtractor(urls)),
backgroundScope = scope,
context,
flowDispatcher = EmptyCoroutineContext,
).apply {
viewing?.let { presentation ->
this.viewEpisode(presentation)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

package me.him188.ani.app.ui.settings.mediasource.selector.test

import android.annotation.SuppressLint
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.SharedTransitionScope
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
Expand All @@ -29,21 +32,30 @@ import me.him188.ani.utils.xml.Document
import me.him188.ani.utils.xml.Element

@Composable
@SuppressLint("UnusedContentLambdaTargetStateParameter")
@Preview
fun PreviewSelectorTestPane() = ProvideFoundationCompositionLocalsForPreview {
val scope = rememberCoroutineScope()
Surface {
SelectorTestPane(
remember {
SelectorTestState(
searchConfigState = mutableStateOf(SelectorSearchConfig.Empty),
engine = TestSelectorMediaSourceEngine(),
scope,
).apply {
subjectSearcher.restartCurrentSearch()
}
},
)
SharedTransitionScope { modifier ->
@Suppress("AnimatedContentLabel")
AnimatedContent(1) { _ ->
Surface {
SelectorTestPane(
remember {
SelectorTestState(
searchConfigState = mutableStateOf(SelectorSearchConfig.Empty),
engine = TestSelectorMediaSourceEngine(),
scope,
).apply {
subjectSearcher.restartCurrentSearch()
}
},
{},
this,
modifier = modifier,
)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fun RefreshIndicatedHeadlineRow(
result: RefreshResult?,
modifier: Modifier = Modifier,
refreshIcon: @Composable () -> Unit = { RefreshIndicationDefaults.RefreshIconButton(onRefresh) },
style: TextStyle = MaterialTheme.typography.headlineSmall,
style: TextStyle = MaterialTheme.typography.titleLarge,
) {
Row(modifier, verticalAlignment = Alignment.CenterVertically) {
ProvideTextStyle(style) {
Expand All @@ -114,7 +114,7 @@ object RefreshIndicationDefaults {
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
TextButton(
IconButton(
onClick = onClick,
modifier = modifier,
) {
Expand Down
Loading

0 comments on commit a40a297

Please sign in to comment.