feat: 支持无图模式
This commit is contained in:
parent
39b1619ad8
commit
ad2ea7eefd
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
) {
|
||||
context.goToActivity<PhotoViewActivity> {
|
||||
putExtra(EXTRA_PHOTO_VIEW_DATA, photoViewData.get() as Parcelable)
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue