feat: 屏蔽视频贴
This commit is contained in:
parent
2ba6b9cc1c
commit
9f6d854572
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue