feat: 用户资料界面 Pad 适配

This commit is contained in:
HuanCheng65 2023-10-08 19:01:44 +08:00
parent bb80c7055d
commit cfdfe9597b
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
6 changed files with 542 additions and 279 deletions

View File

@ -201,7 +201,7 @@ private fun ThreadList(
}
MyLazyColumn(
state = state,
// horizontalAlignment = Alignment.CenterHorizontally,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth(),
contentPadding = WindowInsets.navigationBars.asPaddingValues()
) {

View File

@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@ -68,6 +69,7 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.fastForEachIndexed
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.api.models.protos.User
import com.huanchengfly.tieba.post.arch.BaseComposeActivity.Companion.LocalWindowSizeClass
import com.huanchengfly.tieba.post.arch.GlobalEvent
import com.huanchengfly.tieba.post.arch.ImmutableHolder
import com.huanchengfly.tieba.post.arch.collectPartialAsState
@ -78,6 +80,7 @@ import com.huanchengfly.tieba.post.goToActivity
import com.huanchengfly.tieba.post.models.database.Block
import com.huanchengfly.tieba.post.toastShort
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.ui.common.windowsizeclass.WindowWidthSizeClass
import com.huanchengfly.tieba.post.ui.page.ProvideNavigator
import com.huanchengfly.tieba.post.ui.page.editprofile.view.EditProfileActivity
import com.huanchengfly.tieba.post.ui.page.user.likeforum.UserLikeForumPage
@ -114,7 +117,6 @@ import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.min
@OptIn(ExperimentalFoundationApi::class)
@Destination
@Composable
fun UserProfilePage(
@ -123,9 +125,6 @@ fun UserProfilePage(
viewModel: UserProfileViewModel = pageViewModel(),
) {
val account = LocalAccount.current
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val density = LocalDensity.current
val isSelf = remember(account, uid) {
account?.uid == uid.toString()
@ -160,6 +159,173 @@ fun UserProfilePage(
derivedStateOf { user == null }
}
ProvideNavigator(navigator = navigator) {
StateScreen(
modifier = Modifier.fillMaxSize(),
isEmpty = isEmpty,
isError = isError,
isLoading = isRefreshing,
onReload = { viewModel.send(UserProfileUiIntent.Refresh(uid)) },
errorScreen = { ErrorScreen(error = error.getOrNull()) }
) {
user?.let {
UserProfileContent(
user = it,
showActionBtn = account != null,
disableButton = disableButton,
isSelf = isSelf,
onBack = { navigator.navigateUp() },
onFollow = {
viewModel.send(
UserProfileUiIntent.Follow(
it.get { portrait },
account!!.tbs,
)
)
},
onUnfollow = {
viewModel.send(
UserProfileUiIntent.Unfollow(
it.get { portrait },
account!!.tbs,
)
)
}
)
}
}
}
}
@Composable
private fun UserProfileContent(
user: ImmutableHolder<User>,
showActionBtn: Boolean,
disableButton: Boolean,
isSelf: Boolean,
onBack: () -> Unit,
onFollow: () -> Unit,
onUnfollow: () -> Unit,
) {
when (LocalWindowSizeClass.current.widthSizeClass) {
WindowWidthSizeClass.Expanded -> {
UserProfileContentExpanded(
user = user,
showActionBtn = showActionBtn,
disableButton = disableButton,
isSelf = isSelf,
onBack = onBack,
onFollow = onFollow,
onUnfollow = onUnfollow
)
}
else -> {
UserProfileContentNormal(
user = user,
showActionBtn = showActionBtn,
disableButton = disableButton,
isSelf = isSelf,
onBack = onBack,
onFollow = onFollow,
onUnfollow = onUnfollow
)
}
}
}
@Composable
private fun UserProfileToolbar(
user: ImmutableHolder<User>,
isSelf: Boolean,
showTitle: Boolean,
onBack: () -> Unit,
) {
val context = LocalContext.current
Toolbar(
title = {
AnimatedVisibility(
visible = showTitle,
enter = fadeIn(),
exit = fadeOut()
) {
ToolbarUserTitle(user = user)
}
},
navigationIcon = {
BackNavigationIcon(onBackPressed = onBack)
},
actions = {
user.takeUnless { isSelf }?.let {
ClickMenu(
menuContent = {
DropdownMenuItem(
onClick = {
BlockManager.addBlockAsync(
Block(
category = Block.CATEGORY_BLACK_LIST,
type = Block.TYPE_USER,
username = it.get { name },
uid = it.get { id }.toString()
)
) {
if (it) context.toastShort(R.string.toast_add_success)
}
}
) {
Text(text = stringResource(id = R.string.menu_add_user_to_black_list))
}
DropdownMenuItem(
onClick = {
BlockManager.addBlockAsync(
Block(
category = Block.CATEGORY_WHITE_LIST,
type = Block.TYPE_USER,
username = it.get { name },
uid = it.get { id }.toString()
)
) {
if (it) context.toastShort(R.string.toast_add_success)
}
}
) {
Text(text = stringResource(id = R.string.menu_add_user_to_white_list))
}
},
triggerShape = CircleShape
) {
Box(
modifier = Modifier.size(48.dp),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Rounded.NoAccounts,
contentDescription = stringResource(id = R.string.btn_block)
)
}
}
}
},
)
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun UserProfileContentNormal(
user: ImmutableHolder<User>,
showActionBtn: Boolean,
disableButton: Boolean,
isSelf: Boolean,
onBack: () -> Unit,
onFollow: () -> Unit,
onUnfollow: () -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val density = LocalDensity.current
var heightOffset by rememberSaveable { mutableFloatStateOf(0f) }
var headerHeight by rememberSaveable {
mutableFloatStateOf(
@ -175,268 +341,334 @@ fun UserProfilePage(
}
}
ProvideNavigator(navigator = navigator) {
StateScreen(
modifier = Modifier.fillMaxSize(),
isEmpty = isEmpty,
isError = isError,
isLoading = isRefreshing,
onReload = { viewModel.send(UserProfileUiIntent.Refresh(uid)) },
errorScreen = { ErrorScreen(error = error.getOrNull()) }
MyScaffold(
topBar = {
UserProfileToolbar(
user = user,
isSelf = isSelf,
showTitle = !isShowHeaderArea,
onBack = onBack
)
}
) { paddingValues ->
var isFakeRefreshing by remember { mutableStateOf(false) }
LaunchedEffect(isFakeRefreshing) {
if (isFakeRefreshing) {
delay(1000)
isFakeRefreshing = false
}
}
PullToRefreshLayout(
refreshing = isFakeRefreshing,
onRefresh = {
coroutineScope.emitGlobalEvent(GlobalEvent.Refresh(key = "user_profile"))
isFakeRefreshing = true
}
) {
MyScaffold(
topBar = {
Toolbar(
title = {
user?.let {
AnimatedVisibility(
visible = !isShowHeaderArea,
enter = fadeIn(),
exit = fadeOut()
) {
ToolbarUserTitle(user = it)
}
val headerNestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(
available: Offset,
source: NestedScrollSource,
): Offset {
if (available.y < 0) {
val prevHeightOffset = heightOffset
heightOffset = max(heightOffset + available.y, -headerHeight)
if (prevHeightOffset != heightOffset) {
return available.copy(x = 0f)
}
},
navigationIcon = {
BackNavigationIcon {
navigator.navigateUp()
}
},
actions = {
user.takeUnless { isSelf }?.let {
ClickMenu(
menuContent = {
DropdownMenuItem(
onClick = {
BlockManager.addBlockAsync(
Block(
category = Block.CATEGORY_BLACK_LIST,
type = Block.TYPE_USER,
username = it.get { name },
uid = it.get { id }.toString()
)
) {
if (it) context.toastShort(R.string.toast_add_success)
}
}
) {
Text(text = stringResource(id = R.string.menu_add_user_to_black_list))
}
DropdownMenuItem(
onClick = {
BlockManager.addBlockAsync(
Block(
category = Block.CATEGORY_WHITE_LIST,
type = Block.TYPE_USER,
username = it.get { name },
uid = it.get { id }.toString()
)
) {
if (it) context.toastShort(R.string.toast_add_success)
}
}
) {
Text(text = stringResource(id = R.string.menu_add_user_to_white_list))
}
},
triggerShape = CircleShape
) {
Box(
modifier = Modifier.size(48.dp),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Rounded.NoAccounts,
contentDescription = stringResource(id = R.string.btn_block)
)
}
}
}
},
)
}
) { paddingValues ->
var isFakeRefreshing by remember { mutableStateOf(false) }
}
LaunchedEffect(isFakeRefreshing) {
if (isFakeRefreshing) {
delay(1000)
isFakeRefreshing = false
return Offset.Zero
}
override fun onPostScroll(
consumed: Offset,
available: Offset,
source: NestedScrollSource,
): Offset {
if (available.y > 0f) {
// Adjust the height offset in case the consumed delta Y is less than what was
// recorded as available delta Y in the pre-scroll.
val prevHeightOffset = heightOffset
heightOffset = min(heightOffset + available.y, 0f)
if (prevHeightOffset != heightOffset) {
return available.copy(x = 0f)
}
}
return Offset.Zero
}
}
}
PullToRefreshLayout(
refreshing = isFakeRefreshing,
onRefresh = {
coroutineScope.emitGlobalEvent(GlobalEvent.Refresh(key = "user_profile"))
isFakeRefreshing = true
}
ProvideContentColor(color = ExtendedTheme.colors.text) {
Column(
modifier = Modifier
.padding(paddingValues)
.nestedScroll(headerNestedScrollConnection)
) {
val headerNestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(
available: Offset,
source: NestedScrollSource,
): Offset {
if (available.y < 0) {
val prevHeightOffset = heightOffset
heightOffset = max(heightOffset + available.y, -headerHeight)
if (prevHeightOffset != heightOffset) {
return available.copy(x = 0f)
}
val pages = remember {
listOfNotNull(
UserProfilePageData(
id = "threads",
title = {
stringResource(
id = R.string.title_profile_threads_tab,
it.get { thread_num }.getShortNumString()
)
},
content = { user, fluid ->
UserPostPage(
uid = user.get { id },
isThread = true,
fluid = fluid,
)
}
return Offset.Zero
}
override fun onPostScroll(
consumed: Offset,
available: Offset,
source: NestedScrollSource,
): Offset {
if (available.y > 0f) {
// Adjust the height offset in case the consumed delta Y is less than what was
// recorded as available delta Y in the pre-scroll.
val prevHeightOffset = heightOffset
heightOffset = min(heightOffset + available.y, 0f)
if (prevHeightOffset != heightOffset) {
return available.copy(x = 0f)
}
),
UserProfilePageData(
id = "posts",
title = {
stringResource(
id = R.string.title_profile_posts_tab,
it.get { post_num }.getShortNumString()
)
},
content = { user, fluid ->
UserPostPage(
uid = user.get { id },
isThread = false,
fluid = fluid,
)
}
).takeIf { isSelf },
UserProfilePageData(
id = "concern_forums",
title = {
stringResource(
id = R.string.title_profile_concern_forums_tab,
it.get { my_like_num }.toString()
)
},
content = { user, fluid ->
UserLikeForumPage(
uid = user.get { id },
fluid = fluid,
)
}
),
).toImmutableList()
}
val pagerState = rememberPagerState { pages.size }
return Offset.Zero
val containerHeight by remember {
derivedStateOf {
with(density) {
(headerHeight + heightOffset).toDp()
}
}
}
ProvideContentColor(color = ExtendedTheme.colors.text) {
Column(
Box(
modifier = Modifier
.height(containerHeight)
.clipToBounds()
) {
Box(
modifier = Modifier
.padding(paddingValues)
.nestedScroll(headerNestedScrollConnection)
.wrapContentHeight(
align = Alignment.Bottom,
unbounded = true
)
.onSizeChanged {
headerHeight = it.height.toFloat()
}
) {
user?.let { holder ->
val pages = remember {
listOfNotNull(
UserProfilePageData(
id = "threads",
title = {
stringResource(
id = R.string.title_profile_threads_tab,
it.get { thread_num }.getShortNumString()
)
},
content = {
UserPostPage(
uid = it.get { id },
isThread = true
)
}
),
UserProfilePageData(
id = "posts",
title = {
stringResource(
id = R.string.title_profile_posts_tab,
it.get { post_num }.getShortNumString()
)
},
content = {
UserPostPage(
uid = uid,
isThread = false
)
}
).takeIf { isSelf },
UserProfilePageData(
id = "concern_forums",
title = {
stringResource(
id = R.string.title_profile_concern_forums_tab,
it.get { my_like_num }.toString()
)
},
content = {
UserLikeForumPage(uid = it.get { id })
}
),
).toImmutableList()
}
val pagerState = rememberPagerState { pages.size }
val containerHeight by remember {
derivedStateOf {
with(density) {
(headerHeight + heightOffset).toDp()
}
UserProfileDetail(
user = user,
modifier = Modifier
.padding(16.dp)
.padding(top = 8.dp),
showBtn = showActionBtn,
isSelf = isSelf,
onBtnClick = {
if (disableButton || !showActionBtn) {
return@UserProfileDetail
}
}
Box(
modifier = Modifier
.height(containerHeight)
.clipToBounds()
) {
UserProfileDetail(
user = holder,
modifier = Modifier
.padding(horizontal = 16.dp)
.wrapContentHeight(
align = Alignment.Bottom,
unbounded = true
)
.onSizeChanged {
headerHeight = it.height.toFloat()
},
showBtn = account != null,
isSelf = isSelf,
onBtnClick = {
if (disableButton || account == null) {
return@UserProfileDetail
}
if (isSelf) {
context.goToActivity<EditProfileActivity>()
} else if (holder.get { has_concerned } == 0) {
viewModel.send(
UserProfileUiIntent.Follow(
holder.get { portrait },
account.tbs,
)
)
} else {
viewModel.send(
UserProfileUiIntent.Unfollow(
holder.get { portrait },
account.tbs,
)
)
}
},
onCopyIdClick = {
TiebaUtil.copyText(
context,
holder.get { id }.toString()
)
}
if (isSelf) {
context.goToActivity<EditProfileActivity>()
} else if (user.get { has_concerned } == 0) {
onFollow()
} else {
onUnfollow()
}
},
onCopyIdClick = {
TiebaUtil.copyText(
context,
user.get { id }.toString()
)
}
)
}
}
UserProfileTabRow(
user = holder,
pages = pages,
pagerState = pagerState,
UserProfileTabRow(
user = user,
pages = pages,
pagerState = pagerState,
// modifier = Modifier.padding(horizontal = 16.dp)
)
)
LazyLoadHorizontalPager(
state = pagerState,
key = { pages[it].id },
modifier = Modifier.fillMaxSize()
) {
pages[it].content(holder)
LazyLoadHorizontalPager(
state = pagerState,
key = { pages[it].id },
modifier = Modifier.fillMaxSize()
) {
pages[it].content(user, false)
}
}
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun UserProfileContentExpanded(
user: ImmutableHolder<User>,
showActionBtn: Boolean,
disableButton: Boolean,
isSelf: Boolean,
onBack: () -> Unit,
onFollow: () -> Unit,
onUnfollow: () -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
MyScaffold(
topBar = {
UserProfileToolbar(
user = user,
isSelf = isSelf,
showTitle = false,
onBack = onBack
)
}
) { paddingValues ->
ProvideContentColor(color = ExtendedTheme.colors.text) {
Box(
modifier = Modifier.fillMaxSize()
) {
Row(
modifier = Modifier
.padding(paddingValues)
.fillMaxHeight()
.fillMaxWidth(0.75f)
.align(Alignment.TopCenter),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
val pages = remember {
listOfNotNull(
UserProfilePageData(
id = "threads",
title = {
stringResource(
id = R.string.title_profile_threads_tab,
it.get { thread_num }.getShortNumString()
)
},
content = { user, expanded ->
UserPostPage(
uid = user.get { id },
isThread = true,
fluid = expanded,
enablePullRefresh = expanded,
)
}
),
UserProfilePageData(
id = "posts",
title = {
stringResource(
id = R.string.title_profile_posts_tab,
it.get { post_num }.getShortNumString()
)
},
content = { user, expanded ->
UserPostPage(
uid = user.get { id },
isThread = false,
fluid = expanded,
enablePullRefresh = expanded,
)
}
).takeIf { isSelf },
UserProfilePageData(
id = "concern_forums",
title = {
stringResource(
id = R.string.title_profile_concern_forums_tab,
it.get { my_like_num }.toString()
)
},
content = { user, expanded ->
UserLikeForumPage(
uid = user.get { id },
fluid = expanded,
enablePullRefresh = expanded,
)
}
),
).toImmutableList()
}
val pagerState = rememberPagerState { pages.size }
UserProfileDetail(
user = user,
modifier = Modifier
.weight(1f)
.align(Alignment.Top),
showBtn = showActionBtn,
isSelf = isSelf,
onBtnClick = {
if (disableButton || !showActionBtn) {
return@UserProfileDetail
}
if (isSelf) {
context.goToActivity<EditProfileActivity>()
} else if (user.get { has_concerned } == 0) {
onFollow()
} else {
onUnfollow()
}
},
onCopyIdClick = {
TiebaUtil.copyText(
context,
user.get { id }.toString()
)
}
)
Column(
modifier = Modifier.weight(2f)
) {
UserProfileTabRow(
user = user,
pages = pages,
pagerState = pagerState,
)
LazyLoadHorizontalPager(
state = pagerState,
key = { pages[it].id },
modifier = Modifier.weight(1f)
) {
pages[it].content(user, true)
}
}
}
@ -449,7 +681,7 @@ fun UserProfilePage(
data class UserProfilePageData(
val id: String,
val title: @Composable (ImmutableHolder<User>) -> String,
val content: @Composable (ImmutableHolder<User>) -> Unit,
val content: @Composable (ImmutableHolder<User>, Boolean) -> Unit,
)
@OptIn(ExperimentalFoundationApi::class)
@ -547,7 +779,6 @@ private fun UserProfileDetail(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Spacer(modifier = Modifier.height(16.dp))
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
@ -736,7 +967,6 @@ private fun UserProfileDetail(
)
)
}
Spacer(modifier = Modifier.height(8.dp))
}
}

View File

@ -14,6 +14,7 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
@ -33,6 +34,7 @@ import com.huanchengfly.tieba.post.ui.common.theme.compose.pullRefreshIndicator
import com.huanchengfly.tieba.post.ui.page.LocalNavigator
import com.huanchengfly.tieba.post.ui.page.destinations.ForumPageDestination
import com.huanchengfly.tieba.post.ui.widgets.compose.Avatar
import com.huanchengfly.tieba.post.ui.widgets.compose.Container
import com.huanchengfly.tieba.post.ui.widgets.compose.ErrorScreen
import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad
import com.huanchengfly.tieba.post.ui.widgets.compose.LoadMoreLayout
@ -46,6 +48,8 @@ import kotlinx.collections.immutable.persistentListOf
@Composable
fun UserLikeForumPage(
uid: Long,
fluid: Boolean = false,
enablePullRefresh: Boolean = false,
viewModel: UserLikeForumViewModel = pageViewModel(),
) {
val navigator = LocalNavigator.current
@ -109,7 +113,10 @@ fun UserLikeForumPage(
val lazyListState = rememberLazyListState()
Box {
val pullRefreshModifier =
if (enablePullRefresh) Modifier.pullRefresh(pullRefreshState) else Modifier
Box(modifier = pullRefreshModifier) {
LoadMoreLayout(
isLoading = isLoadingMore,
onLoadMore = {
@ -120,6 +127,7 @@ fun UserLikeForumPage(
) {
UserLikeForumList(
data = forums,
fluid = fluid,
onClickForum = { forumBean ->
forumBean.name?.let {
navigator.navigate(ForumPageDestination(it))
@ -144,6 +152,7 @@ fun UserLikeForumPage(
private fun UserLikeForumList(
data: ImmutableList<UserLikeForumBean.ForumBean>,
onClickForum: (UserLikeForumBean.ForumBean) -> Unit,
fluid: Boolean = false,
lazyListState: LazyListState = rememberLazyListState(),
) {
MyLazyColumn(state = lazyListState) {
@ -151,15 +160,17 @@ private fun UserLikeForumList(
items = data,
key = { it.id }
) {
UserLikeForumItem(
item = it,
onClick = {
onClickForum(it)
},
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
)
Container(fluid = fluid) {
UserLikeForumItem(
item = it,
onClick = {
onClickForum(it)
},
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
)
}
}
}
}

View File

@ -20,6 +20,7 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
@ -52,6 +53,7 @@ import com.huanchengfly.tieba.post.ui.page.destinations.ThreadPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.UserProfilePageDestination
import com.huanchengfly.tieba.post.ui.widgets.compose.Button
import com.huanchengfly.tieba.post.ui.widgets.compose.Card
import com.huanchengfly.tieba.post.ui.widgets.compose.Container
import com.huanchengfly.tieba.post.ui.widgets.compose.ErrorScreen
import com.huanchengfly.tieba.post.ui.widgets.compose.FeedCard
import com.huanchengfly.tieba.post.ui.widgets.compose.FeedCardPlaceholder
@ -70,6 +72,8 @@ import kotlinx.collections.immutable.persistentListOf
fun UserPostPage(
uid: Long,
isThread: Boolean = true,
fluid: Boolean = false,
enablePullRefresh: Boolean = false,
viewModel: UserPostViewModel = pageViewModel(key = if (isThread) "user_thread_$uid" else "user_post_$uid"),
) {
val navigator = LocalNavigator.current
@ -207,7 +211,10 @@ fun UserPostPage(
val lazyListState = rememberLazyListState()
Box {
val pullRefreshModifier =
if (enablePullRefresh) Modifier.pullRefresh(pullRefreshState) else Modifier
Box(modifier = pullRefreshModifier) {
LoadMoreLayout(
isLoading = isLoadingMore,
onLoadMore = {
@ -218,6 +225,7 @@ fun UserPostPage(
) {
UserPostList(
data = posts,
fluid = fluid,
lazyListState = lazyListState,
onClickItem = { threadId, postId, isSubPost ->
if (postId == null) {
@ -286,6 +294,7 @@ fun UserPostPage(
@Composable
private fun UserPostList(
data: ImmutableList<PostListItemData>,
fluid: Boolean = false,
lazyListState: LazyListState = rememberLazyListState(),
onClickItem: (threadId: Long, postId: Long?, isSubPost: Boolean) -> Unit = { _, _, _ -> },
onAgreeItem: (PostInfoList) -> Unit = {},
@ -301,15 +310,17 @@ private fun UserPostList(
"${it.data.get { thread_id }}_${it.data.get { post_id }}"
}
) { itemData ->
UserPostItem(
post = itemData,
onClick = onClickItem,
onAgree = onAgreeItem,
onClickReply = onClickReply,
onClickUser = onClickUser,
onClickForum = onClickForum,
onClickOriginThread = onClickOriginThread,
)
Container(fluid = fluid) {
UserPostItem(
post = itemData,
onClick = onClickItem,
onAgree = onAgreeItem,
onClickReply = onClickReply,
onClickUser = onClickUser,
onClickForum = onClickForum,
onClickOriginThread = onClickOriginThread,
)
}
}
}
}

View File

@ -12,14 +12,19 @@ import com.huanchengfly.tieba.post.ui.common.windowsizeclass.WindowWidthSizeClas
@Composable
fun Container(
modifier: Modifier = Modifier,
fluid: Boolean = false,
content: @Composable () -> Unit,
) {
val windowWidthSizeClass = LocalWindowSizeClass.current.widthSizeClass
val widthFraction = remember(windowWidthSizeClass) {
when (windowWidthSizeClass) {
WindowWidthSizeClass.Medium -> 0.87f
WindowWidthSizeClass.Expanded -> 0.75f
else -> 1f
if (fluid) {
1f
} else {
when (windowWidthSizeClass) {
WindowWidthSizeClass.Medium -> 0.87f
WindowWidthSizeClass.Expanded -> 0.75f
else -> 1f
}
}
}

View File

@ -25,14 +25,19 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.TipScreen
val DefaultLoadingScreen: @Composable StateScreenScope.() -> Unit = {
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.lottie_loading_paperplane))
Box(modifier = Modifier.requiredWidthIn(max = 500.dp)) {
LottieAnimation(
composition = composition,
iterations = LottieConstants.IterateForever,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(2f)
)
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
Box(modifier = Modifier.requiredWidthIn(max = 500.dp)) {
LottieAnimation(
composition = composition,
iterations = LottieConstants.IterateForever,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(2f)
)
}
}
// CircularProgressIndicator(modifier = Modifier.size(48.dp), color = MaterialTheme.colors.primary)
}
@ -56,7 +61,8 @@ val DefaultEmptyScreen: @Composable StateScreenScope.() -> Unit = {
Text(text = stringResource(id = R.string.btn_refresh))
}
}
}
},
modifier = Modifier.fillMaxWidth(),
)
}