feat: 支持无图模式

This commit is contained in:
HuanCheng65 2023-07-24 09:23:06 +08:00
parent 39b1619ad8
commit ad2ea7eefd
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
9 changed files with 106 additions and 154 deletions

View File

@ -656,6 +656,7 @@ class App : Application(), IApp, SketchFactory {
context.getColorCompat(R.color.theme_color_nav_bar_surface_light)
}
}
R.attr.colorOnNavBarSurface -> {
return if (ThemeUtil.isNightMode(theme)) {
context.getColorCompat(R.color.theme_color_on_nav_bar_surface_dark)
@ -663,6 +664,20 @@ class App : Application(), IApp, SketchFactory {
context.getColorCompat(R.color.theme_color_on_nav_bar_surface_light)
}
}
R.attr.colorPlaceholder -> {
return if (ThemeUtil.isTranslucentTheme(theme) || ThemeUtil.isNightMode(theme)) {
context.getColorCompat(
resources.getIdentifier(
"theme_color_placeholder_$theme",
"color",
packageName
)
)
} else {
context.getColorCompat(R.color.theme_color_placeholder_light)
}
}
}
return Util.getColorByAttr(context, attrId, R.color.transparent)
}

View File

@ -1,5 +1,6 @@
package com.huanchengfly.tieba.post.ui.common.theme.compose
import android.annotation.SuppressLint
import androidx.compose.material.Colors
import androidx.compose.material.ContentAlpha
import androidx.compose.material.MaterialTheme
@ -22,67 +23,40 @@ import com.huanchengfly.tieba.post.utils.compose.darken
data class ExtendedColors(
val theme: String,
val isNightMode: Boolean,
val primary: Color,
val accent: Color,
val onAccent: Color,
val topBar: Color,
val onTopBar: Color,
val onTopBarSecondary: Color,
val onTopBarActive: Color,
val topBarSurface: Color,
val onTopBarSurface: Color,
val bottomBar: Color,
val bottomBarSurface: Color,
val onBottomBarSurface: Color,
val text: Color,
val textSecondary: Color,
val textOnPrimary: Color,
val textDisabled: Color,
val background: Color,
val chip: Color,
val onChip: Color,
val unselected: Color,
val card: Color,
val floorCard: Color,
val divider: Color,
val shadow: Color,
val indicator: Color,
val windowBackground: Color,
val primary: Color = Color.Unspecified,
val accent: Color = Color.Unspecified,
val onAccent: Color = Color.Unspecified,
val topBar: Color = Color.Unspecified,
val onTopBar: Color = Color.Unspecified,
val onTopBarSecondary: Color = Color.Unspecified,
val onTopBarActive: Color = Color.Unspecified,
val topBarSurface: Color = Color.Unspecified,
val onTopBarSurface: Color = Color.Unspecified,
val bottomBar: Color = Color.Unspecified,
val bottomBarSurface: Color = Color.Unspecified,
val onBottomBarSurface: Color = Color.Unspecified,
val text: Color = Color.Unspecified,
val textSecondary: Color = Color.Unspecified,
val textOnPrimary: Color = Color.Unspecified,
val textDisabled: Color = Color.Unspecified,
val background: Color = Color.Unspecified,
val chip: Color = Color.Unspecified,
val onChip: Color = Color.Unspecified,
val unselected: Color = Color.Unspecified,
val card: Color = Color.Unspecified,
val floorCard: Color = Color.Unspecified,
val divider: Color = Color.Unspecified,
val shadow: Color = Color.Unspecified,
val indicator: Color = Color.Unspecified,
val windowBackground: Color = Color.Unspecified,
val placeholder: Color = Color.Unspecified,
)
val LocalExtendedColors = staticCompositionLocalOf {
ExtendedColors(
"",
false,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
)
ExtendedColors("", false)
}
@SuppressLint("ConflictingOnColor")
fun getColorPalette(
darkTheme: Boolean,
extendedColors: ExtendedColors
@ -172,13 +146,7 @@ private fun getThemeColorForTheme(theme: String): ExtendedColors {
Color(App.ThemeDelegate.getColorByAttr(App.INSTANCE, R.attr.colorFloorCard, nowTheme)),
Color(App.ThemeDelegate.getColorByAttr(App.INSTANCE, R.attr.colorDivider, nowTheme)),
Color(App.ThemeDelegate.getColorByAttr(App.INSTANCE, R.attr.shadow_color, nowTheme)),
Color(
App.ThemeDelegate.getColorByAttr(
App.INSTANCE,
R.attr.colorIndicator,
nowTheme
)
),
Color(App.ThemeDelegate.getColorByAttr(App.INSTANCE, R.attr.colorIndicator, nowTheme)),
Color(
App.ThemeDelegate.getColorByAttr(
App.INSTANCE,
@ -186,6 +154,7 @@ private fun getThemeColorForTheme(theme: String): ExtendedColors {
nowTheme
)
),
Color(App.ThemeDelegate.getColorByAttr(App.INSTANCE, R.attr.colorPlaceholder, nowTheme)),
)
}

View File

@ -8,10 +8,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
@ -30,11 +27,9 @@ import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
@ -45,10 +40,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.placeholder.material.placeholder
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo
import com.huanchengfly.tieba.post.api.models.protos.hasAgree
import com.huanchengfly.tieba.post.arch.GlobalEvent
import com.huanchengfly.tieba.post.arch.ImmutableHolder
import com.huanchengfly.tieba.post.arch.collectPartialAsState
import com.huanchengfly.tieba.post.arch.onGlobalEvent
import com.huanchengfly.tieba.post.arch.pageViewModel
@ -63,7 +56,6 @@ import com.huanchengfly.tieba.post.ui.page.destinations.HotTopicListPageDestinat
import com.huanchengfly.tieba.post.ui.page.destinations.ThreadPageDestination
import com.huanchengfly.tieba.post.ui.widgets.compose.FeedCard
import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad
import com.huanchengfly.tieba.post.ui.widgets.compose.NetworkImage
import com.huanchengfly.tieba.post.ui.widgets.compose.ProvideContentColor
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalGrid
@ -394,74 +386,6 @@ private fun ThreadListItemPlaceholder() {
}
}
@Composable
private fun ThreadListItem(
index: Int,
itemHolder: ImmutableHolder<ThreadInfo>,
onClick: (ThreadInfo) -> Unit = {}
) {
val item = remember(itemHolder) { itemHolder.get() }
val heightModifier = if (item.media.isEmpty()) Modifier else Modifier.height(80.dp)
Row(
modifier = Modifier
.clickable { onClick(item) }
.padding(all = 16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
Row(
modifier = heightModifier.weight(1f),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.Top
) {
Text(
text = "${index + 1}",
fontWeight = FontWeight.Bold,
fontSize = 10.sp,
color = ExtendedTheme.colors.background,
modifier = Modifier
.padding(top = 2.dp)
.clip(RoundedCornerShape(4.dp))
.wrapContentSize()
.background(
color = when (index) {
0 -> RedA700
1 -> OrangeA700
2 -> Yellow
else -> MaterialTheme.colors.onBackground.copy(
ContentAlpha.medium
)
}
)
.padding(vertical = 1.dp, horizontal = 4.dp)
)
Column(verticalArrangement = Arrangement.SpaceBetween, modifier = heightModifier) {
Text(text = item.title, maxLines = 2, overflow = TextOverflow.Ellipsis)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(id = R.string.hot_num, item.hotNum.getShortNumString()),
style = MaterialTheme.typography.caption,
color = ExtendedTheme.colors.textSecondary
)
}
}
if (!item.videoInfo?.thumbnailUrl.isNullOrBlank()) {
NetworkImage(
imageUri = item.videoInfo?.thumbnailUrl!!,
contentDescription = null,
modifier = heightModifier.aspectRatio(16f / 9),
contentScale = ContentScale.Crop
)
} else if (!item.media.firstOrNull()?.dynamicPic.isNullOrBlank()) {
NetworkImage(
imageUri = item.media.first().dynamicPic,
contentDescription = null,
modifier = heightModifier.aspectRatio(16f / 9),
contentScale = ContentScale.Crop
)
}
}
}
@Composable
private fun ThreadListTab(
text: String,

View File

@ -81,8 +81,14 @@ fun Avatar(
size: Dp,
contentDescription: String?,
modifier: Modifier = Modifier,
shape: Shape = CircleShape,
) {
Avatar(data = data, contentDescription = contentDescription, modifier = modifier.size(size))
Avatar(
data = data,
contentDescription = contentDescription,
modifier = modifier.size(size),
shape = shape,
)
}
@Composable
@ -90,6 +96,7 @@ fun Avatar(
data: String?,
contentDescription: String?,
modifier: Modifier = Modifier,
shape: Shape = CircleShape,
) {
val context = LocalContext.current
@ -100,8 +107,7 @@ fun Avatar(
},
contentDescription = contentDescription,
contentScale = ContentScale.Crop,
modifier = modifier
.clip(CircleShape),
modifier = modifier.clip(shape),
)
}

View File

@ -311,13 +311,13 @@ private fun ForumInfoChip(
.padding(4.dp),
verticalAlignment = Alignment.CenterVertically,
) {
NetworkImage(
imageUri = imageUri,
Avatar(
data = imageUri,
contentDescription = null,
modifier = Modifier
.fillMaxHeight()
.aspectRatio(1f)
.clip(RoundedCornerShape(4.dp))
.aspectRatio(1f),
shape = RoundedCornerShape(4.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
@ -391,7 +391,9 @@ private fun ThreadMedia(
NetworkImage(
imageUri = remember(media) { media.url },
contentDescription = null,
modifier = Modifier.weight(1f),
modifier = Modifier
.fillMaxHeight()
.weight(1f),
photoViewData = photoViewData,
contentScale = ContentScale.Crop
)

View File

@ -1,16 +1,20 @@
package com.huanchengfly.tieba.post.ui.widgets.compose
import android.content.Context
import android.os.Parcelable
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import com.github.panpf.sketch.compose.AsyncImage
import com.github.panpf.sketch.request.Depth
import com.github.panpf.sketch.request.DisplayRequest
import com.huanchengfly.tieba.post.arch.ImmutableHolder
import com.huanchengfly.tieba.post.goToActivity
@ -18,6 +22,19 @@ import com.huanchengfly.tieba.post.models.protos.PhotoViewData
import com.huanchengfly.tieba.post.ui.page.photoview.PhotoViewActivity
import com.huanchengfly.tieba.post.ui.page.photoview.PhotoViewActivity.Companion.EXTRA_PHOTO_VIEW_DATA
import com.huanchengfly.tieba.post.utils.ImageUtil
import com.huanchengfly.tieba.post.utils.NetworkUtil
import com.huanchengfly.tieba.post.utils.appPreferences
fun shouldLoadImage(context: Context, skipNetworkCheck: Boolean): Boolean {
val imageLoadSettings =
context.appPreferences.imageLoadType?.toIntOrNull() ?: ImageUtil.SETTINGS_SMART_ORIGIN
return skipNetworkCheck
|| imageLoadSettings == ImageUtil.SETTINGS_SMART_ORIGIN
|| imageLoadSettings == ImageUtil.SETTINGS_ALL_ORIGIN
|| (imageLoadSettings == ImageUtil.SETTINGS_SMART_LOAD && NetworkUtil.isWifiConnected(
context
))
}
@Composable
fun NetworkImage(
@ -26,26 +43,34 @@ fun NetworkImage(
modifier: Modifier = Modifier,
photoViewData: ImmutableHolder<PhotoViewData>? = null,
contentScale: ContentScale = ContentScale.Fit,
skipNetworkCheck: Boolean = false,
) {
val context = LocalContext.current
val clickableModifier = if (photoViewData != null) {
var shouldLoad by remember { mutableStateOf(shouldLoadImage(context, skipNetworkCheck)) }
val clickableModifier = if (photoViewData != null || !shouldLoad) {
Modifier.clickable(
indication = null,
interactionSource = remember {
MutableInteractionSource()
}
interactionSource = remember { MutableInteractionSource() }
) {
if (!shouldLoad) {
shouldLoad = true
} else if (photoViewData != null) {
context.goToActivity<PhotoViewActivity> {
putExtra(EXTRA_PHOTO_VIEW_DATA, photoViewData.get() as Parcelable)
}
}
}
} else Modifier
val request = remember(imageUri) {
val request = remember(imageUri, shouldLoad) {
DisplayRequest(context, imageUri) {
placeholder(ImageUtil.getPlaceHolder(context, 0))
crossfade()
if (!shouldLoad) {
depth(Depth.LOCAL)
}
}
}
AsyncImage(
request = request,
contentDescription = contentDescription,
@ -61,6 +86,7 @@ fun NetworkImage(
modifier: Modifier = Modifier,
photoViewDataProvider: (() -> ImmutableHolder<PhotoViewData>)? = null,
contentScale: ContentScale = ContentScale.Fit,
skipNetworkCheck: Boolean = false,
) {
val imageUri by rememberUpdatedState(newValue = imageUriProvider())
val photoViewData by rememberUpdatedState(newValue = photoViewDataProvider?.invoke())
@ -71,5 +97,6 @@ fun NetworkImage(
modifier = modifier,
photoViewData = photoViewData,
contentScale = contentScale,
skipNetworkCheck = skipNetworkCheck,
)
}

View File

@ -28,6 +28,7 @@
<attr name="colorDivider" format="color" />
<attr name="shadow_color" format="color" />
<attr name="colorIndicator" format="color" />
<attr name="colorPlaceholder" format="color" />
</declare-styleable>
<declare-styleable name="ShadowLayout">

View File

@ -243,6 +243,13 @@
<color name="theme_color_shadow_day">@color/color_shadow</color>
<color name="theme_color_shadow_night">#FE191919</color>
<color name="theme_color_placeholder_light">#FFF0F0F0</color>
<color name="theme_color_placeholder_blue_dark">#99000000</color>
<color name="theme_color_placeholder_grey_dark">#99000000</color>
<color name="theme_color_placeholder_amoled_dark">#99000000</color>
<color name="theme_color_placeholder_translucent_light">#15FFFFFF</color>
<color name="theme_color_placeholder_translucent_dark">#30000000</color>
<color name="red_accent">#FFC51100</color>
<color name="color_divider">#FFF7FBFE</color>

View File

@ -707,4 +707,5 @@
<string name="below_is_latest_post">以下为最新回复</string>
<string name="btn_open_origin_thread">查看原贴</string>
<string name="tip_blocked_thread">由于你的屏蔽设置,该贴已被屏蔽</string>
<string name="desc_picture">图片</string>
</resources>