feat: 屏蔽视频贴

This commit is contained in:
HuanCheng65 2023-07-13 22:11:13 +08:00
parent 2ba6b9cc1c
commit 9f6d854572
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
6 changed files with 63 additions and 16 deletions

View File

@ -1,6 +1,7 @@
package com.huanchengfly.tieba.post.ui.page.forum.threadlist package com.huanchengfly.tieba.post.ui.page.forum.threadlist
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.huanchengfly.tieba.post.App
import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.TiebaApi
import com.huanchengfly.tieba.post.api.models.AgreeBean import com.huanchengfly.tieba.post.api.models.AgreeBean
import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo
@ -18,6 +19,7 @@ import com.huanchengfly.tieba.post.arch.UiIntent
import com.huanchengfly.tieba.post.arch.UiState import com.huanchengfly.tieba.post.arch.UiState
import com.huanchengfly.tieba.post.arch.wrapImmutable import com.huanchengfly.tieba.post.arch.wrapImmutable
import com.huanchengfly.tieba.post.repository.FrsPageRepository import com.huanchengfly.tieba.post.repository.FrsPageRepository
import com.huanchengfly.tieba.post.utils.appPreferences
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -102,7 +104,7 @@ private class ForumThreadListPartialChangeProducer(val type: ForumThreadListType
val userList = response.data_.user_list val userList = response.data_.user_list
val threadList = response.data_.thread_list.map { threadInfo -> val threadList = response.data_.thread_list.map { threadInfo ->
threadInfo.copy(author = userList.find { it.id == threadInfo.authorId }) threadInfo.copy(author = userList.find { it.id == threadInfo.authorId })
} }.filter { !App.INSTANCE.appPreferences.blockVideo || it.videoInfo == null }
ForumThreadListPartialChange.FirstLoad.Success( ForumThreadListPartialChange.FirstLoad.Success(
threadList.wrapImmutable(), threadList.wrapImmutable(),
response.data_.thread_id_list, response.data_.thread_id_list,

View File

@ -226,7 +226,7 @@ fun PersonalizedPage(
@Composable @Composable
private fun FeedList( private fun FeedList(
dataProvider: () -> List<ImmutableHolder<ThreadInfo>>, dataProvider: () -> List<ImmutableHolder<ThreadInfo>>,
personalizedDataProvider: () -> List<ImmutableHolder<ThreadPersonalized>>, personalizedDataProvider: () -> List<ImmutableHolder<ThreadPersonalized>?>,
refreshPositionProvider: () -> Int, refreshPositionProvider: () -> Int,
hiddenThreadIdsProvider: () -> List<Long>, hiddenThreadIdsProvider: () -> List<Long>,
onItemClick: (ThreadInfo) -> Unit, onItemClick: (ThreadInfo) -> Unit,
@ -278,7 +278,7 @@ private fun FeedList(
if (personalized != null) { if (personalized != null) {
Dislike( Dislike(
personalized = threadPersonalizedData[index], personalized = personalized,
onDislike = { clickTime, reasons -> onDislike = { clickTime, reasons ->
onDislike(item.get(), clickTime, reasons) onDislike(item.get(), clickTime, reasons)
} }

View File

@ -1,6 +1,7 @@
package com.huanchengfly.tieba.post.ui.page.main.explore.personalized package com.huanchengfly.tieba.post.ui.page.main.explore.personalized
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.huanchengfly.tieba.post.App
import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.TiebaApi
import com.huanchengfly.tieba.post.api.models.AgreeBean import com.huanchengfly.tieba.post.api.models.AgreeBean
import com.huanchengfly.tieba.post.api.models.CommonResponse import com.huanchengfly.tieba.post.api.models.CommonResponse
@ -19,6 +20,7 @@ import com.huanchengfly.tieba.post.arch.UiIntent
import com.huanchengfly.tieba.post.arch.UiState import com.huanchengfly.tieba.post.arch.UiState
import com.huanchengfly.tieba.post.arch.wrapImmutable import com.huanchengfly.tieba.post.arch.wrapImmutable
import com.huanchengfly.tieba.post.models.DislikeBean import com.huanchengfly.tieba.post.models.DislikeBean
import com.huanchengfly.tieba.post.utils.appPreferences
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -28,6 +30,7 @@ import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import okhttp3.internal.toImmutableList
import javax.inject.Inject import javax.inject.Inject
@Stable @Stable
@ -62,11 +65,17 @@ class PersonalizedViewModel @Inject constructor() :
private fun produceRefreshPartialChange(): Flow<PersonalizedPartialChange.Refresh> = private fun produceRefreshPartialChange(): Flow<PersonalizedPartialChange.Refresh> =
TiebaApi.getInstance().personalizedProtoFlow(1, 1) TiebaApi.getInstance().personalizedProtoFlow(1, 1)
.map<PersonalizedResponse, PersonalizedPartialChange.Refresh> { .map<PersonalizedResponse, PersonalizedPartialChange.Refresh> { response ->
val data = response.toData().filter {
!App.INSTANCE.appPreferences.blockVideo || it.get { videoInfo } == null
}
val threadPersonalizedData = data.map { thread ->
response.data_?.thread_personalized?.firstOrNull { thread.get { id } == it.tid }
?.wrapImmutable()
}
PersonalizedPartialChange.Refresh.Success( PersonalizedPartialChange.Refresh.Success(
data = it.toData(), data = data,
threadPersonalizedData = (it.data_?.thread_personalized threadPersonalizedData = threadPersonalizedData.toImmutableList(),
?: emptyList()).wrapImmutable(),
) )
} }
.onStart { emit(PersonalizedPartialChange.Refresh.Start) } .onStart { emit(PersonalizedPartialChange.Refresh.Start) }
@ -74,12 +83,18 @@ class PersonalizedViewModel @Inject constructor() :
private fun PersonalizedUiIntent.LoadMore.producePartialChange(): Flow<PersonalizedPartialChange.LoadMore> = private fun PersonalizedUiIntent.LoadMore.producePartialChange(): Flow<PersonalizedPartialChange.LoadMore> =
TiebaApi.getInstance().personalizedProtoFlow(2, page) TiebaApi.getInstance().personalizedProtoFlow(2, page)
.map<PersonalizedResponse, PersonalizedPartialChange.LoadMore> { .map<PersonalizedResponse, PersonalizedPartialChange.LoadMore> { response ->
val data = response.toData().filter {
!App.INSTANCE.appPreferences.blockVideo || it.get { videoInfo } == null
}
val threadPersonalizedData = data.map { thread ->
response.data_?.thread_personalized?.firstOrNull { thread.get { id } == it.tid }
?.wrapImmutable()
}
PersonalizedPartialChange.LoadMore.Success( PersonalizedPartialChange.LoadMore.Success(
currentPage = page, currentPage = page,
data = it.toData(), data = data,
threadPersonalizedData = (it.data_?.thread_personalized threadPersonalizedData = threadPersonalizedData.toImmutableList(),
?: emptyList()).wrapImmutable(),
) )
} }
.onStart { emit(PersonalizedPartialChange.LoadMore.Start) } .onStart { emit(PersonalizedPartialChange.LoadMore.Start) }
@ -261,7 +276,7 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
data class Success( data class Success(
val data: List<ImmutableHolder<ThreadInfo>>, val data: List<ImmutableHolder<ThreadInfo>>,
val threadPersonalizedData: List<ImmutableHolder<ThreadPersonalized>>, val threadPersonalizedData: List<ImmutableHolder<ThreadPersonalized>?>,
) : Refresh() ) : Refresh()
data class Failure( data class Failure(
@ -287,7 +302,7 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
data class Success( data class Success(
val currentPage: Int, val currentPage: Int,
val data: List<ImmutableHolder<ThreadInfo>>, val data: List<ImmutableHolder<ThreadInfo>>,
val threadPersonalizedData: List<ImmutableHolder<ThreadPersonalized>>, val threadPersonalizedData: List<ImmutableHolder<ThreadPersonalized>?>,
) : LoadMore() ) : LoadMore()
data class Failure( data class Failure(
@ -302,7 +317,7 @@ data class PersonalizedUiState(
val isLoadingMore: Boolean = false, val isLoadingMore: Boolean = false,
val currentPage: Int = 1, val currentPage: Int = 1,
val data: List<ImmutableHolder<ThreadInfo>> = emptyList(), val data: List<ImmutableHolder<ThreadInfo>> = emptyList(),
val threadPersonalizedData: List<ImmutableHolder<ThreadPersonalized>> = emptyList(), val threadPersonalizedData: List<ImmutableHolder<ThreadPersonalized>?> = emptyList(),
val hiddenThreadIds: List<Long> = emptyList(), val hiddenThreadIds: List<Long> = emptyList(),
val refreshPosition: Int = 0, val refreshPosition: Int = 0,
): UiState ): UiState

View File

@ -4,7 +4,14 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.* import androidx.compose.material.icons.outlined.CalendarViewDay
import androidx.compose.material.icons.outlined.ExitToApp
import androidx.compose.material.icons.outlined.Extension
import androidx.compose.material.icons.outlined.PhotoSizeSelectActual
import androidx.compose.material.icons.outlined.SecurityUpdateWarning
import androidx.compose.material.icons.outlined.StarOutline
import androidx.compose.material.icons.outlined.Verified
import androidx.compose.material.icons.rounded.VideocamOff
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -23,7 +30,11 @@ import com.huanchengfly.tieba.post.ui.common.prefs.widgets.ListPref
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.SwitchPref import com.huanchengfly.tieba.post.ui.common.prefs.widgets.SwitchPref
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.TextPref import com.huanchengfly.tieba.post.ui.common.prefs.widgets.TextPref
import com.huanchengfly.tieba.post.ui.page.settings.LeadingIcon import com.huanchengfly.tieba.post.ui.page.settings.LeadingIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.* import com.huanchengfly.tieba.post.ui.widgets.compose.AvatarIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.BackNavigationIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.MyScaffold
import com.huanchengfly.tieba.post.ui.widgets.compose.Sizes
import com.huanchengfly.tieba.post.ui.widgets.compose.TitleCentredToolbar
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.DestinationsNavigator
@ -92,6 +103,22 @@ fun HabitSettingsPage(
}, },
) )
} }
prefsItem {
SwitchPref(
key = "blockVideo",
title = stringResource(id = R.string.settings_block_video),
defaultChecked = false,
leadingIcon = {
LeadingIcon {
AvatarIcon(
icon = Icons.Rounded.VideocamOff,
size = Sizes.Small,
contentDescription = null,
)
}
}
)
}
prefsItem { prefsItem {
ListPref( ListPref(
key = "default_sort_type", key = "default_sort_type",

View File

@ -47,6 +47,8 @@ open class AppPreferencesUtils(private val context: Context) {
key = "auto_sign_time" key = "auto_sign_time"
) )
var blockVideo by DataStoreDelegates.boolean(defaultValue = false)
var checkCIUpdate by DataStoreDelegates.boolean( var checkCIUpdate by DataStoreDelegates.boolean(
defaultValue = false defaultValue = false
) )

View File

@ -674,4 +674,5 @@
<string name="open_all_sub_posts">查看全部 %d 条回复</string> <string name="open_all_sub_posts">查看全部 %d 条回复</string>
<string name="message_store_thread_update">贴子更新到了第 %d 楼</string> <string name="message_store_thread_update">贴子更新到了第 %d 楼</string>
<string name="tip_blocked_post">由于你的屏蔽设置,第 %d 楼已被屏蔽</string> <string name="tip_blocked_post">由于你的屏蔽设置,第 %d 楼已被屏蔽</string>
<string name="settings_block_video">屏蔽视频贴子</string>
</resources> </resources>