diff --git a/app/src/main/java/com/aiosman/riderpro/data/MomentService.kt b/app/src/main/java/com/aiosman/riderpro/data/MomentService.kt index e564af0..d59b2d2 100644 --- a/app/src/main/java/com/aiosman/riderpro/data/MomentService.kt +++ b/app/src/main/java/com/aiosman/riderpro/data/MomentService.kt @@ -78,7 +78,9 @@ data class Image( @SerializedName("url") val url: String, @SerializedName("thumbnail") - val thumbnail: String + val thumbnail: String, + @SerializedName("blurHash") + val blurHash: String? ) data class User( diff --git a/app/src/main/java/com/aiosman/riderpro/ui/Navi.kt b/app/src/main/java/com/aiosman/riderpro/ui/Navi.kt index d1ffb78..2abed98 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/Navi.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/Navi.kt @@ -37,7 +37,7 @@ import com.aiosman.riderpro.ui.login.EmailSignupScreen import com.aiosman.riderpro.ui.login.LoginPage import com.aiosman.riderpro.ui.login.SignupScreen import com.aiosman.riderpro.ui.login.UserAuthScreen -import com.aiosman.riderpro.ui.message.NotificationsScreen +import com.aiosman.riderpro.ui.index.tabs.message.NotificationsScreen import com.aiosman.riderpro.ui.modification.EditModificationScreen import com.aiosman.riderpro.ui.post.NewPostScreen import com.aiosman.riderpro.ui.post.PostScreen diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/Index.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/Index.kt index 9ad293e..805854b 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/Index.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/Index.kt @@ -26,11 +26,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import com.aiosman.riderpro.ui.index.tabs.add.AddPage +import com.aiosman.riderpro.ui.index.tabs.message.NotificationsScreen import com.aiosman.riderpro.ui.index.tabs.moment.MomentsList import com.aiosman.riderpro.ui.index.tabs.profile.ProfilePage import com.aiosman.riderpro.ui.index.tabs.search.SearchScreen import com.aiosman.riderpro.ui.index.tabs.shorts.ShortVideo import com.aiosman.riderpro.ui.index.tabs.street.StreetPage +import com.aiosman.riderpro.ui.message.MessagePage import com.google.accompanist.systemuicontroller.rememberSystemUiController @Composable @@ -45,6 +47,7 @@ fun IndexScreen() { // NavigationItem.Street, NavigationItem.Add, // NavigationItem.Message, + NavigationItem.Notification, NavigationItem.Profile ) val systemUiController = rememberSystemUiController() @@ -101,6 +104,7 @@ fun IndexScreen() { ) { Home() } + 1 -> Box( modifier = Modifier.padding(innerPadding) ) { @@ -115,9 +119,14 @@ fun IndexScreen() { // 3 -> Box( // modifier = Modifier.padding(innerPadding) // ) { Video() } - 3 -> Box( modifier = Modifier.padding(innerPadding) + ) { + Notifications() + } + + 4 -> Box( + modifier = Modifier.padding(innerPadding) ) { Profile() } } } @@ -205,4 +214,20 @@ fun Profile() { ) { ProfilePage() } +} + +@Composable +fun Notifications() { + val systemUiController = rememberSystemUiController() + LaunchedEffect(Unit) { + systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true) + } + Column( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + NotificationsScreen() + } } \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/NavigationItem.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/NavigationItem.kt index b0a09df..cb25218 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/NavigationItem.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/NavigationItem.kt @@ -33,6 +33,11 @@ sealed class NavigationItem( selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_video) } ) + data object Notification : NavigationItem("Notification", + icon = { ImageVector.vectorResource(R.drawable.rider_pro_notification) }, + selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_notification) } + ) + data object Profile : NavigationItem("Profile", icon = { ImageVector.vectorResource(R.drawable.rider_pro_profile) }, selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_profile_filed) } diff --git a/app/src/main/java/com/aiosman/riderpro/ui/message/MessageList.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageList.kt similarity index 78% rename from app/src/main/java/com/aiosman/riderpro/ui/message/MessageList.kt rename to app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageList.kt index ddc3380..2e65eee 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/message/MessageList.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageList.kt @@ -1,4 +1,4 @@ -package com.aiosman.riderpro.ui.message +package com.aiosman.riderpro.ui.index.tabs.message import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -32,7 +32,6 @@ import androidx.compose.ui.unit.sp import androidx.paging.compose.collectAsLazyPagingItems import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.R -import com.aiosman.riderpro.data.Comment import com.aiosman.riderpro.data.CommentEntity import com.aiosman.riderpro.exp.timeAgo import com.aiosman.riderpro.ui.NavigationRoute @@ -49,80 +48,82 @@ fun NotificationsScreen() { val model = MessageListViewModel val navController = LocalNavController.current val systemUiController = rememberSystemUiController() - var dataFlow = model.commentItemsFlow + var dataFlow = MessageListViewModel.commentItemsFlow var comments = dataFlow.collectAsLazyPagingItems() LaunchedEffect(Unit) { systemUiController.setNavigationBarColor(Color.Transparent) - model.initData() + MessageListViewModel.initData() } - StatusBarMaskLayout(darkIcons = true) { - Column( + Column( + modifier = Modifier.fillMaxSize() + + ) { + Box( modifier = Modifier .fillMaxWidth() - .weight(1f) + .padding(horizontal = 24.dp, vertical = 16.dp) ) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp, vertical = 16.dp) + Image( + painter = painterResource(id = R.drawable.rider_pro_message_title), + contentDescription = "Back", + modifier = Modifier.width(120.dp) + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + NotificationIndicator( + MessageListViewModel.likeNoticeCount, + R.drawable.rider_pro_like, + "LIKE" ) { - Image( - painter = painterResource(id = R.drawable.rider_pro_message_title), - contentDescription = "Back", - modifier = Modifier.width(120.dp) - ) + navController.navigate(NavigationRoute.Likes.route) } - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween, + NotificationIndicator( + MessageListViewModel.followNoticeCount, + R.drawable.rider_pro_followers, + "FOLLOWERS" ) { - NotificationIndicator(model.likeNoticeCount, R.drawable.rider_pro_like, "LIKE") { - navController.navigate(NavigationRoute.Likes.route) - } - NotificationIndicator( - model.followNoticeCount, - R.drawable.rider_pro_followers, - "FOLLOWERS" - ) { - navController.navigate(NavigationRoute.Followers.route) - } - NotificationIndicator( - model.favouriteNoticeCount, - R.drawable.rider_pro_favoriate, - "Favourites" - ) { - navController.navigate(NavigationRoute.FavouritesScreen.route) - } + navController.navigate(NavigationRoute.Followers.route) } - HorizontalDivider(color = Color(0xFFEbEbEb), modifier = Modifier.padding(16.dp)) - NotificationCounterItem(model.commentNoticeCount) - LazyColumn( - modifier = Modifier - .weight(1f) - .fillMaxSize() + NotificationIndicator( + MessageListViewModel.favouriteNoticeCount, + R.drawable.rider_pro_favoriate, + "Favourites" ) { - items(comments.itemCount) { index -> - comments[index]?.let { comment -> - CommentItem(comment) { - model.updateReadStatus(comment.id) - navController.navigate( - NavigationRoute.Post.route.replace( - "{id}", - comment.postId.toString() - ) + navController.navigate(NavigationRoute.FavouritesScreen.route) + } + } + HorizontalDivider(color = Color(0xFFEbEbEb), modifier = Modifier.padding(16.dp)) + NotificationCounterItem(MessageListViewModel.commentNoticeCount) + LazyColumn( + modifier = Modifier + .weight(1f) + .fillMaxSize() + ) { + items(comments.itemCount) { index -> + comments[index]?.let { comment -> + CommentItem(comment) { + MessageListViewModel.updateReadStatus(comment.id) + navController.navigate( + NavigationRoute.Post.route.replace( + "{id}", + comment.postId.toString() ) - } + ) } } - item { - BottomNavigationPlaceholder() - } + } + item { + BottomNavigationPlaceholder() } } } + } @Composable diff --git a/app/src/main/java/com/aiosman/riderpro/ui/message/MessageListViewModel.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageListViewModel.kt similarity index 98% rename from app/src/main/java/com/aiosman/riderpro/ui/message/MessageListViewModel.kt rename to app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageListViewModel.kt index 12ca610..75a80a7 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/message/MessageListViewModel.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageListViewModel.kt @@ -1,4 +1,4 @@ -package com.aiosman.riderpro.ui.message +package com.aiosman.riderpro.ui.index.tabs.message import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt index 588adee..815a87a 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt @@ -2,10 +2,12 @@ package com.aiosman.riderpro.ui.index.tabs.moment import androidx.annotation.DrawableRes import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -21,6 +23,9 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Build @@ -42,6 +47,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext @@ -59,6 +65,7 @@ import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.LocalSharedTransitionScope import com.aiosman.riderpro.R import com.aiosman.riderpro.model.MomentEntity +import com.aiosman.riderpro.model.MomentImageEntity import com.aiosman.riderpro.ui.NavigationRoute import com.aiosman.riderpro.ui.comment.CommentModalContent import com.aiosman.riderpro.ui.composables.AnimatedCounter @@ -66,6 +73,7 @@ import com.aiosman.riderpro.ui.composables.AnimatedFavouriteIcon import com.aiosman.riderpro.ui.composables.AnimatedLikeIcon import com.aiosman.riderpro.ui.composables.CustomAsyncImage import com.aiosman.riderpro.ui.composables.RelPostCard +import com.aiosman.riderpro.ui.imageviewer.ImageViewerViewModel import com.aiosman.riderpro.ui.modifiers.noRippleClickable import com.aiosman.riderpro.ui.post.NewPostViewModel import com.google.accompanist.systemuicontroller.rememberSystemUiController @@ -140,7 +148,11 @@ fun MomentCard( Column( modifier = Modifier.fillMaxWidth() ) { - MomentTopRowGroup(momentEntity = momentEntity) + Box( + modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp) + ) { + MomentTopRowGroup(momentEntity = momentEntity) + } Column( modifier = Modifier .fillMaxWidth() @@ -154,7 +166,7 @@ fun MomentCard( .fillMaxHeight() .weight(1f) // ModificationListHeader() - if (!hideAction){ + if (!hideAction) { MomentBottomOperateRowGroup( momentOperateBtnBoxModifier, momentEntity = momentEntity, @@ -274,8 +286,6 @@ fun MomentTopRowGroup(momentEntity: MomentEntity) { val context = LocalContext.current Row( modifier = Modifier - .height(40.dp) - .padding(top = 0.dp, bottom = 0.dp, start = 24.dp, end = 24.dp) ) { CustomAsyncImage( context, @@ -320,45 +330,108 @@ fun MomentTopRowGroup(momentEntity: MomentEntity) { } } -@OptIn(ExperimentalSharedTransitionApi::class) +@OptIn(ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class) +@Composable +fun PostImageView( + postId: String, + images: List, +) { + val pagerState = rememberPagerState(pageCount = { images.size }) + val navController = LocalNavController.current + val sharedTransitionScope = LocalSharedTransitionScope.current + val animatedVisibilityScope = LocalAnimatedContentScope.current + val context = LocalContext.current + + Column( + modifier = Modifier.fillMaxWidth() + ) { + HorizontalPager( + state = pagerState, + modifier = Modifier + .fillMaxWidth() + .aspectRatio(1f), + ) { page -> + val image = images[page] + with(sharedTransitionScope) { + CustomAsyncImage( + context, + image.thumbnail, + contentDescription = "Image", + contentScale = ContentScale.Crop, + modifier = Modifier + .sharedElement( + rememberSharedContentState(key = image), + animatedVisibilityScope = animatedVisibilityScope + ) + .fillMaxSize() +// .noRippleClickable { +// ImageViewerViewModel.asNew(images, page) +// navController.navigate( +// NavigationRoute.ImageViewer.route +// ) +// } + ) + } + } + + // Indicator container + if (images.size > 1) { + Row( + modifier = Modifier + .padding(8.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + images.forEachIndexed { index, _ -> + Box( + modifier = Modifier + .size(8.dp) + .clip(CircleShape) + + .background( + if (pagerState.currentPage == index) Color.Red else Color.Gray.copy( + alpha = 0.5f + ) + ) + .padding(4.dp) + + + ) + Spacer(modifier = Modifier.width(8.dp)) + } + } + } + + } + +} + @Composable fun MomentContentGroup( momentEntity: MomentEntity, ) { - val displayImageUrl = momentEntity.images.firstOrNull() - val sharedTransitionScope = LocalSharedTransitionScope.current - val animatedVisibilityScope = LocalAnimatedContentScope.current - val context = LocalContext.current - Text( - text = "${momentEntity.momentTextContent}", - modifier = Modifier - .fillMaxWidth() - .padding(top = 22.dp, bottom = 16.dp, start = 24.dp, end = 24.dp), - fontSize = 16.sp - ) + if (momentEntity.momentTextContent.isNotEmpty()) { + Text( + text = momentEntity.momentTextContent, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp, vertical = 8.dp), + fontSize = 16.sp + ) + } if (momentEntity.relMoment != null) { RelPostCard( momentEntity = momentEntity.relMoment!!, modifier = Modifier.background(Color(0xFFF8F8F8)) ) } else { - displayImageUrl?.let { - with(sharedTransitionScope) { - CustomAsyncImage( - context, - it.thumbnail, - modifier = Modifier - .sharedElement( - rememberSharedContentState(key = it), - animatedVisibilityScope = animatedVisibilityScope - ) - .fillMaxWidth() - .aspectRatio(1f), - contentScale = ContentScale.Crop, - contentDescription = "" - ) - } - + Box( + modifier = Modifier.fillMaxWidth() + ) { + PostImageView( + postId = momentEntity.id.toString(), + images = momentEntity.images + ) } } diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt index 074e7dc..9c73039 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt @@ -374,50 +374,6 @@ fun CommunicationOperatorGroup( } } - if (isSelf) { - Box( - modifier = Modifier - .size(width = 142.dp, height = 40.dp) - .padding(start = 6.dp) - .clickable { - navController.navigate("MyMessage") - }, - contentAlignment = Alignment.Center - ) { - Image( - modifier = Modifier.fillMaxSize(), - painter = painterResource(id = R.drawable.rider_pro_profile_message), - contentDescription = "" - ) - Text( - text = "MESSAGE", - fontSize = 16.sp, - color = Color.White, - style = TextStyle(fontWeight = FontWeight.Bold) - ) - } -// Box( -// modifier = Modifier -// .size(width = 142.dp, height = 40.dp) -// .clickable { -// navController.navigate("ProfileTimeline") -// }, -// contentAlignment = Alignment.Center -// ) { -// Image( -// modifier = Modifier.fillMaxSize(), -// painter = painterResource(id = R.drawable.rider_pro_profile_follow), -// contentDescription = "" -// ) -// Text( -// text = "GALLERY", -// fontSize = 16.sp, -// color = Color.White, -// style = TextStyle(fontWeight = FontWeight.Bold) -// ) -// } - } - } } diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/search/SearchScreen.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/search/SearchScreen.kt index 36300b4..98b7d0a 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/search/SearchScreen.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/search/SearchScreen.kt @@ -70,10 +70,10 @@ fun SearchScreen() { modifier = Modifier .background(Color.White) .fillMaxSize() - .padding(start = 16.dp, end = 16.dp, top = 24.dp) + ) { SearchInput( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().padding(top = 16.dp, start = 24.dp, end = 24.dp), text = model.searchText, onTextChange = { model.searchText = it @@ -125,7 +125,7 @@ fun SearchInput( .clip(shape = RoundedCornerShape(8.dp)) .background(Color(0xFFEEEEEE)) - .padding(horizontal = 16.dp, vertical = 16.dp) + .padding(horizontal = 16.dp, vertical = 8.dp) ) { Row( verticalAlignment = Alignment.CenterVertically diff --git a/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt b/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt index 19ca160..d77604c 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt @@ -52,9 +52,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -109,7 +111,7 @@ class PostViewModel( ) : ViewModel() { var service: MomentService = TestMomentServiceImpl() var commentService: CommentService = TestCommentServiceImpl() - var userService : UserService = TestUserServiceImpl() + var userService: UserService = TestUserServiceImpl() private var _commentsFlow = MutableStateFlow>(PagingData.empty()) val commentsFlow = _commentsFlow.asStateFlow() @@ -308,7 +310,6 @@ fun PostScreen( modifier = Modifier .fillMaxWidth() .aspectRatio(1f) - ) { PostImageView( id, @@ -403,7 +404,8 @@ fun Header( modifier = Modifier .height(20.dp) .wrapContentWidth() - .padding(start = 6.dp).noRippleClickable { + .padding(start = 6.dp) + .noRippleClickable { onFollowClick() }, contentAlignment = Alignment.Center @@ -441,7 +443,7 @@ fun PostImageView( state = pagerState, modifier = Modifier .weight(1f) - .fillMaxWidth(), + .fillMaxWidth().background(Color.Gray.copy(alpha = 0.1f)), ) { page -> val image = images[page] with(sharedTransitionScope) { @@ -449,7 +451,7 @@ fun PostImageView( context, image.thumbnail, contentDescription = "Image", - contentScale = ContentScale.Fit, + contentScale = ContentScale.Crop, modifier = Modifier .sharedElement( rememberSharedContentState(key = image), @@ -661,7 +663,7 @@ fun BottomNavigationBar( onLikeClick() }) { Icon( - Icons.Filled.Favorite, + imageVector = ImageVector.vectorResource(id = R.drawable.rider_pro_like), contentDescription = "like", tint = if (momentEntity?.liked == true) Color.Red else Color.Gray ) @@ -673,7 +675,7 @@ fun BottomNavigationBar( } ) { Icon( - Icons.Filled.Star, + imageVector = ImageVector.vectorResource(id = R.drawable.rider_pro_favoriate), contentDescription = "Favourite", tint = if (momentEntity?.isFavorite == true) Color.Red else Color.Gray )