From 052493058a71cc26f391fd25943a8e713f9955bf Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 28 Sep 2024 22:48:43 +0100 Subject: [PATCH] =?UTF-8?q?MediaListFilterContext:=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=89=A7=E9=9B=86=20ep=20=E5=92=8C=E5=90=8D=E7=A7=B0=E5=88=A4?= =?UTF-8?q?=E5=AE=9A,=20=E8=BF=9B=E8=80=8C=E5=A2=9E=E5=8A=A0=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E5=87=86=E7=A1=AE=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../media/source/MediaListFilterContext.kt | 5 +++++ .../source/media/source/MediaListFilters.kt | 15 ++++++++++++++- .../data/source/media/source/RssMediaSource.kt | 6 ++++++ .../source/media/source/RssMediaSourceEngine.kt | 2 +- .../media/source/web/SelectorMediaSource.kt | 2 ++ .../source/web/SelectorMediaSourceEngine.kt | 6 +++++- .../media/source/MediaListFilterSamples.kt | 17 +++++++++++++++-- .../settings/mediasource/rss/test/RssInfoTab.kt | 2 +- .../mediasource/rss/test/RssTestPaneState.kt | 2 ++ .../selector/test/SelectorTestState.kt | 2 ++ 10 files changed, 53 insertions(+), 6 deletions(-) diff --git a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilterContext.kt b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilterContext.kt index 456a83a2b8..8d44229757 100644 --- a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilterContext.kt +++ b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilterContext.kt @@ -20,12 +20,17 @@ import me.him188.ani.datasources.api.EpisodeSort open class MediaListFilterContext( val subjectNames: Set, // faster val episodeSort: EpisodeSort, + val episodeEp: EpisodeSort?, + val episodeName: String?, ) { val subjectNamesWithoutSpecial: Set by lazy { subjectNames.mapTo(HashSet(subjectNames.size)) { it.replace(MediaListFilters.specialCharRegex, "") } } + val episodeNameWithoutSpecial: String? by lazy { + episodeName?.replace(MediaListFilters.specialCharRegex, "") + } /** * 返回 `true` 表示该 [Candidate] 符合过滤条件. diff --git a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilters.kt b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilters.kt index b4e6c22a0c..3a17d5618a 100644 --- a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilters.kt +++ b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/MediaListFilters.kt @@ -18,7 +18,7 @@ import me.him188.ani.datasources.api.topic.contains */ object MediaListFilters { val specialCharRegex = Regex("""[ ~!@#$%^&*()_+{}\[\]\\|;':",.<>/?【】]""") - + val ContainsSubjectName = BasicMediaListFilter { media -> subjectNamesWithoutSpecial.any { subjectName -> media.originalTitle.replace(specialCharRegex, "") @@ -30,4 +30,17 @@ object MediaListFilters { val range = media.episodeRange ?: return@BasicMediaListFilter false range.contains(episodeSort) } + val ContainsEpisodeEp = BasicMediaListFilter { media -> + val range = media.episodeRange ?: return@BasicMediaListFilter false + episodeEp != null && range.contains(episodeEp) + } + val ContainsEpisodeName = BasicMediaListFilter { media -> + episodeName ?: return@BasicMediaListFilter false + val name = episodeNameWithoutSpecial + checkNotNull(name) + if (name.isBlank()) return@BasicMediaListFilter false + media.originalTitle.replace(specialCharRegex, "").contains(name) + } + + val ContainsAnyEpisodeInfo = ContainsEpisodeSort or ContainsEpisodeName or ContainsEpisodeEp } diff --git a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSource.kt b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSource.kt index 1d76fcc5b3..a2533cf9cf 100644 --- a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSource.kt +++ b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSource.kt @@ -166,6 +166,8 @@ class RssMediaSource( subjectName = name, episodeSort = query.episodeSort, allSubjectNames = query.subjectNames, + episodeEp = query.episodeEp, + episodeName = query.episodeName, ), ).map { MediaMatch(it, MatchKind.FUZZY) @@ -178,9 +180,13 @@ data class RssSearchQuery( val subjectName: String, val allSubjectNames: Set, val episodeSort: EpisodeSort, + val episodeEp: EpisodeSort?, + val episodeName: String?, ) fun RssSearchQuery.toFilterContext() = MediaListFilterContext( subjectNames = allSubjectNames, episodeSort = episodeSort, + episodeEp = episodeSort, + episodeName = episodeName, ) diff --git a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSourceEngine.kt b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSourceEngine.kt index b95d00d5c2..99ee154a8b 100644 --- a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSourceEngine.kt +++ b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/RssMediaSourceEngine.kt @@ -149,7 +149,7 @@ data class RssSearchConfig( */ fun RssSearchConfig.createFilters() = buildList { if (filterBySubjectName) add(MediaListFilters.ContainsSubjectName) - if (filterByEpisodeSort) add(MediaListFilters.ContainsEpisodeSort) + if (filterByEpisodeSort) add(MediaListFilters.ContainsAnyEpisodeInfo) } /** diff --git a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSource.kt b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSource.kt index ef49906bf8..8dda21f245 100644 --- a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSource.kt +++ b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSource.kt @@ -196,6 +196,8 @@ class SelectorMediaSource( subjectName = name, episodeSort = query.episodeSort, allSubjectNames = query.subjectNames, + episodeEp = query.episodeEp, + episodeName = query.episodeName, ), mediaSourceId, ).getOrThrow().asFlow() diff --git a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSourceEngine.kt b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSourceEngine.kt index a6236627e1..aa5ade0c49 100644 --- a/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSourceEngine.kt +++ b/app/shared/app-data/src/commonMain/kotlin/data/source/media/source/web/SelectorMediaSourceEngine.kt @@ -51,11 +51,15 @@ data class SelectorSearchQuery( val subjectName: String, val allSubjectNames: Set, val episodeSort: EpisodeSort, + val episodeEp: EpisodeSort?, + val episodeName: String?, ) fun SelectorSearchQuery.toFilterContext() = MediaListFilterContext( subjectNames = allSubjectNames, episodeSort = episodeSort, + episodeEp = episodeEp, + episodeName = episodeName, ) /** @@ -300,7 +304,7 @@ internal fun SelectorSearchConfig.createFiltersForSubject() = buildList { internal fun SelectorSearchConfig.createFiltersForEpisode() = buildList { // 不使用 filterBySubjectName, 因为 web 的剧集名称通常为 "第x集", 不包含 subject - if (filterByEpisodeSort) add(MediaListFilters.ContainsEpisodeSort) + if (filterByEpisodeSort) add(MediaListFilters.ContainsAnyEpisodeInfo) } class DefaultSelectorMediaSourceEngine( diff --git a/app/shared/src/commonTest/kotlin/data/source/media/source/MediaListFilterSamples.kt b/app/shared/src/commonTest/kotlin/data/source/media/source/MediaListFilterSamples.kt index c979787d8e..17d6ba04e9 100644 --- a/app/shared/src/commonTest/kotlin/data/source/media/source/MediaListFilterSamples.kt +++ b/app/shared/src/commonTest/kotlin/data/source/media/source/MediaListFilterSamples.kt @@ -1,3 +1,12 @@ +/* + * Copyright (C) 2024 OpenAni and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link. + * + * https://github.com/open-ani/ani/blob/main/LICENSE + */ + @file:Suppress("unused", "UNUSED_VARIABLE") package me.him188.ani.app.data.source.media.source @@ -16,10 +25,14 @@ fun applyingFilters(mediaList: List) { if (enableFilterBySubjectName) { add(MediaListFilters.ContainsSubjectName) } - add(MediaListFilters.ContainsEpisodeSort) + add(MediaListFilters.ContainsAnyEpisodeInfo) } - val newList: List = with(MediaListFilterContext(setOf("条目名称"), EpisodeSort(1))) { + val context = MediaListFilterContext( + setOf("条目名称"), EpisodeSort(1), EpisodeSort(1), + "第1集", + ) + val newList: List = with(context) { mediaList.filter { media -> filters.applyOn(media.asCandidate()) } diff --git a/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssInfoTab.kt b/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssInfoTab.kt index a46c8e9625..6241fb8173 100644 --- a/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssInfoTab.kt +++ b/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssInfoTab.kt @@ -123,7 +123,7 @@ class RssItemPresentation( } else { emit( episodeRange.toString(), - isMatch = MediaListFilters.ContainsEpisodeSort.applyOn(candidate), + isMatch = MediaListFilters.ContainsAnyEpisodeInfo.applyOn(candidate), ) } } else { diff --git a/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssTestPaneState.kt b/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssTestPaneState.kt index 06544a5c50..f1035b839d 100644 --- a/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssTestPaneState.kt +++ b/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/rss/test/RssTestPaneState.kt @@ -98,6 +98,8 @@ class RssTestPaneState( subjectName = testData.keyword, episodeSort = EpisodeSort(sort), allSubjectNames = setOf(testData.keyword), + episodeName = null, + episodeEp = null, ) viewingItem = null launchRequestInBackground { diff --git a/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/selector/test/SelectorTestState.kt b/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/selector/test/SelectorTestState.kt index 7dc2f5e644..727d549816 100644 --- a/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/selector/test/SelectorTestState.kt +++ b/app/shared/ui-settings/src/commonMain/kotlin/ui/settings/mediasource/selector/test/SelectorTestState.kt @@ -45,6 +45,8 @@ class SelectorTestState( subjectName = searchKeyword, episodeSort = EpisodeSort(sort), allSubjectNames = setOf(searchKeyword), + episodeName = null, + episodeEp = null, ) } }