添加业务逻辑
This commit is contained in:
@@ -80,6 +80,8 @@ dependencies {
|
|||||||
implementation(libs.androidx.animation)
|
implementation(libs.androidx.animation)
|
||||||
implementation("io.coil-kt:coil-compose:2.7.0")
|
implementation("io.coil-kt:coil-compose:2.7.0")
|
||||||
implementation("io.coil-kt:coil:2.7.0")
|
implementation("io.coil-kt:coil:2.7.0")
|
||||||
|
implementation("com.google.android.gms:play-services-auth:21.2.0")
|
||||||
|
implementation("io.github.serpro69:kotlin-faker:2.0.0-rc.5")
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.aiosman.riderpro.data
|
||||||
|
|
||||||
|
data class AccountProfile(
|
||||||
|
val id: Int,
|
||||||
|
val followerCount: Int,
|
||||||
|
val followingCount: Int,
|
||||||
|
val nickName: String,
|
||||||
|
val avatar: String,
|
||||||
|
val bio: String,
|
||||||
|
val country: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
interface AccountService {
|
||||||
|
suspend fun getAccountProfile(): AccountProfile
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestAccountServiceImpl : AccountService {
|
||||||
|
override suspend fun getAccountProfile(): AccountProfile {
|
||||||
|
return AccountProfile(
|
||||||
|
id = 1,
|
||||||
|
followerCount = 100,
|
||||||
|
followingCount = 200,
|
||||||
|
nickName = "Aiosman",
|
||||||
|
avatar = "https://img.freepik.com/free-photo/white-billboard-template_23-2147726635.jpg?t=st=1722150015~exp=1722153615~hmac=5540620196d7898215d822be26353c87a63d51bbfb2b814e032626e1948a1583&w=740",
|
||||||
|
bio = "I am a software engineer",
|
||||||
|
country = "Nigeria"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
package com.aiosman.riderpro.data.comment
|
package com.aiosman.riderpro.data
|
||||||
|
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.paging.PagingState
|
import androidx.paging.PagingState
|
||||||
import com.aiosman.riderpro.data.ListContainer
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@@ -1,17 +1,15 @@
|
|||||||
package com.aiosman.riderpro.data.moment
|
package com.aiosman.riderpro.data
|
||||||
|
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.paging.PagingState
|
import androidx.paging.PagingState
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.data.ListContainer
|
|
||||||
import com.aiosman.riderpro.model.MomentItem
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
|
import com.aiosman.riderpro.test.TestDatabase
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
class MomentPagingSource(
|
class MomentPagingSource(
|
||||||
private val remoteDataSource: MomentRemoteDataSource,
|
private val remoteDataSource: MomentRemoteDataSource,
|
||||||
) : PagingSource<Int, MomentItem>() {
|
) : PagingSource<Int, MomentItem>() {
|
||||||
|
|
||||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentItem> {
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentItem> {
|
||||||
return try {
|
return try {
|
||||||
val currentPage = params.key ?: 1
|
val currentPage = params.key ?: 1
|
||||||
@@ -46,6 +44,7 @@ class MomentRemoteDataSource(
|
|||||||
interface MomentService {
|
interface MomentService {
|
||||||
suspend fun getMoments(pageNumber: Int): ListContainer<MomentItem>
|
suspend fun getMoments(pageNumber: Int): ListContainer<MomentItem>
|
||||||
suspend fun getMomentById(id: Int): MomentItem
|
suspend fun getMomentById(id: Int): MomentItem
|
||||||
|
suspend fun likeMoment(id: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestMomentServiceImpl() : MomentService {
|
class TestMomentServiceImpl() : MomentService {
|
||||||
@@ -54,23 +53,7 @@ class TestMomentServiceImpl() : MomentService {
|
|||||||
"https://img.freepik.com/free-photo/minimal-clothing-label-fashion-brands_53876-111053.jpg?w=1060&t=st=1722150122~exp=1722150722~hmac=67f8a2b6abfe3d08714cf0cc0085485c3221e1ba00dda14378b03753dce39153",
|
"https://img.freepik.com/free-photo/minimal-clothing-label-fashion-brands_53876-111053.jpg?w=1060&t=st=1722150122~exp=1722150722~hmac=67f8a2b6abfe3d08714cf0cc0085485c3221e1ba00dda14378b03753dce39153",
|
||||||
"https://img.freepik.com/free-photo/marketing-strategy-planning-strategy-concept_53876-42950.jpg"
|
"https://img.freepik.com/free-photo/marketing-strategy-planning-strategy-concept_53876-42950.jpg"
|
||||||
)
|
)
|
||||||
val mockData = (0..300).toList().mapIndexed { idx, _ ->
|
var mockData = TestDatabase.momentData
|
||||||
MomentItem(
|
|
||||||
id = idx,
|
|
||||||
avatar = R.drawable.default_avatar,
|
|
||||||
nickname = "Onyama Limba",
|
|
||||||
location = "Japan",
|
|
||||||
time = "2023.02.02 11:23",
|
|
||||||
followStatus = false,
|
|
||||||
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
|
|
||||||
momentPicture = R.drawable.default_moment_img,
|
|
||||||
likeCount = 21,
|
|
||||||
commentCount = 43,
|
|
||||||
shareCount = 33,
|
|
||||||
favoriteCount = 211,
|
|
||||||
images = imageList.shuffled().take(3),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val testMomentBackend = TestMomentBackend(mockData)
|
val testMomentBackend = TestMomentBackend(mockData)
|
||||||
override suspend fun getMoments(pageNumber: Int): ListContainer<MomentItem> {
|
override suspend fun getMoments(pageNumber: Int): ListContainer<MomentItem> {
|
||||||
return testMomentBackend.fetchMomentItems(pageNumber)
|
return testMomentBackend.fetchMomentItems(pageNumber)
|
||||||
@@ -79,6 +62,18 @@ class TestMomentServiceImpl() : MomentService {
|
|||||||
override suspend fun getMomentById(id: Int): MomentItem {
|
override suspend fun getMomentById(id: Int): MomentItem {
|
||||||
return mockData[id]
|
return mockData[id]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun likeMoment(id: Int) {
|
||||||
|
// mockData = mockData.map {
|
||||||
|
// if (it.id == id) {
|
||||||
|
// it.copy(likeCount = it.likeCount + 1)
|
||||||
|
// } else {
|
||||||
|
// it
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// mockData
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestMomentBackend(
|
class TestMomentBackend(
|
||||||
18
app/src/main/java/com/aiosman/riderpro/data/UserService.kt
Normal file
18
app/src/main/java/com/aiosman/riderpro/data/UserService.kt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package com.aiosman.riderpro.data
|
||||||
|
|
||||||
|
import com.aiosman.riderpro.test.TestDatabase
|
||||||
|
|
||||||
|
interface UserService {
|
||||||
|
suspend fun getUserProfile(id:String): AccountProfile
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestUserServiceImpl : UserService {
|
||||||
|
override suspend fun getUserProfile(id: String): AccountProfile {
|
||||||
|
TestDatabase.accountData.forEach {
|
||||||
|
if (it.id == id.toInt()) {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AccountProfile(0, 0, 0, "", "", "", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import com.aiosman.riderpro.R
|
|||||||
|
|
||||||
data class MomentItem(
|
data class MomentItem(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
@DrawableRes val avatar: Int,
|
val avatar: String,
|
||||||
val nickname: String,
|
val nickname: String,
|
||||||
val location: String,
|
val location: String,
|
||||||
val time: String,
|
val time: String,
|
||||||
@@ -16,61 +16,6 @@ data class MomentItem(
|
|||||||
val commentCount: Int,
|
val commentCount: Int,
|
||||||
val shareCount: Int,
|
val shareCount: Int,
|
||||||
val favoriteCount: Int,
|
val favoriteCount: Int,
|
||||||
val images: List<String> = emptyList()
|
val images: List<String> = emptyList(),
|
||||||
)
|
val authorId: Int = 0
|
||||||
|
|
||||||
val momentTestItem = MomentItem(
|
|
||||||
id = 1,
|
|
||||||
avatar = R.drawable.default_avatar,
|
|
||||||
nickname = "Onyama Limba",
|
|
||||||
location = "Japan",
|
|
||||||
time = "2023.02.02 11:23",
|
|
||||||
followStatus = false,
|
|
||||||
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
|
|
||||||
momentPicture = R.drawable.default_moment_img,
|
|
||||||
likeCount = 21,
|
|
||||||
commentCount = 43,
|
|
||||||
shareCount = 33,
|
|
||||||
favoriteCount = 211)
|
|
||||||
|
|
||||||
val profileMomentItems = listOf(
|
|
||||||
MomentItem(
|
|
||||||
id = 1,
|
|
||||||
avatar = R.drawable.default_avatar,
|
|
||||||
nickname = "Onyama Limba",
|
|
||||||
location = "Japan",
|
|
||||||
time = "2024.06.08 12:23",
|
|
||||||
followStatus = false,
|
|
||||||
momentTextContent = "Modifications that are made to make your motorbike more like you",
|
|
||||||
momentPicture = R.drawable.rider_pro_moment_demo_1,
|
|
||||||
likeCount = 2345,
|
|
||||||
commentCount = 12,
|
|
||||||
shareCount = 33,
|
|
||||||
favoriteCount = 211),
|
|
||||||
MomentItem(
|
|
||||||
id = 2,
|
|
||||||
avatar = R.drawable.default_avatar,
|
|
||||||
nickname = "Onyama Limba",
|
|
||||||
location = "Japan",
|
|
||||||
time = "2024.03.03 12:31",
|
|
||||||
followStatus = false,
|
|
||||||
momentTextContent = "At least 500 units will be made, to meet homologation requirements.",
|
|
||||||
momentPicture = R.drawable.rider_pro_moment_demo_2,
|
|
||||||
likeCount = 211,
|
|
||||||
commentCount = 33,
|
|
||||||
shareCount = 33,
|
|
||||||
favoriteCount = 211),
|
|
||||||
MomentItem(
|
|
||||||
id = 3,
|
|
||||||
avatar = R.drawable.default_avatar,
|
|
||||||
nickname = "Onyama Limba",
|
|
||||||
location = "Japan",
|
|
||||||
time = "2024.02.02 11:23",
|
|
||||||
followStatus = false,
|
|
||||||
momentTextContent = "The bike is already FIM legal (and soon-to-be MotoAmerica legal as well).",
|
|
||||||
momentPicture = R.drawable.rider_pro_moment_demo_3,
|
|
||||||
likeCount = 987,
|
|
||||||
commentCount = 21,
|
|
||||||
shareCount = 33,
|
|
||||||
favoriteCount = 211)
|
|
||||||
)
|
)
|
||||||
|
|||||||
92
app/src/main/java/com/aiosman/riderpro/test/TestDatabase.kt
Normal file
92
app/src/main/java/com/aiosman/riderpro/test/TestDatabase.kt
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package com.aiosman.riderpro.test
|
||||||
|
|
||||||
|
import com.aiosman.riderpro.R
|
||||||
|
import com.aiosman.riderpro.data.AccountProfile
|
||||||
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
|
import io.github.serpro69.kfaker.faker
|
||||||
|
|
||||||
|
object TestDatabase {
|
||||||
|
var momentData = emptyList<MomentItem>()
|
||||||
|
var accountData = emptyList<AccountProfile>()
|
||||||
|
var imageList = listOf(
|
||||||
|
"https://img.freepik.com/free-photo/white-billboard-template_23-2147726635.jpg?t=st=1722150015~exp=1722153615~hmac=5540620196d7898215d822be26353c87a63d51bbfb2b814e032626e1948a1583&w=740",
|
||||||
|
"https://img.freepik.com/free-photo/minimal-clothing-label-fashion-brands_53876-111053.jpg?w=1060&t=st=1722150122~exp=1722150722~hmac=67f8a2b6abfe3d08714cf0cc0085485c3221e1ba00dda14378b03753dce39153",
|
||||||
|
"https://img.freepik.com/free-photo/marketing-strategy-planning-strategy-concept_53876-42950.jpg",
|
||||||
|
"https://t4.ftcdn.net/jpg/02/27/00/89/240_F_227008949_5O7yXuEqTwUgs3BGqdcvrNutM5MSxs1t.jpg",
|
||||||
|
|
||||||
|
"https://t4.ftcdn.net/jpg/01/86/86/49/240_F_186864971_NixcoDg1zBjjN7soUNhpEVraI4vdzOFD.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/00/84/01/30/240_F_84013057_fsOdzBgskSFUyWyD6YKjIAdtKdBPiKRD.jpg",
|
||||||
|
"https://t4.ftcdn.net/jpg/00/93/89/23/240_F_93892312_SNyGGruVaWKpJQiVG314gIQmS4EAghdy.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/02/94/56/58/240_F_294565895_IOqZC2OpcHGEibWF04MPEP09KZaewEl5.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/01/01/66/84/240_F_101668484_FopHBSMBq4t6BlvwI9awPMzUdi501sJ7.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/05/65/11/60/240_F_565116019_oHbZ6Hc8VYCMcZWpexXF7Z5lOWeNNYtD.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/03/52/21/48/240_F_352214843_dQ3JtTJrKyqrh2yd1emYCDPSrzrwqaNK.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/07/22/47/16/240_F_722471661_T25r329RFRxgK88S6oBJ9dUksOC2arLl.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/02/18/11/26/240_F_218112603_jBChzLJGuz8smPZsdFsy17wB0O0QF3Xo.jpg",
|
||||||
|
"https://t4.ftcdn.net/jpg/04/11/49/07/240_F_411490703_KRvV0aRyxHWYVUO8bGXxuQGo2mHblYnv.jpg",
|
||||||
|
"https://img.freepik.com/premium-photo/man-wearing-orange-helmet-white-background_466494-5539.jpg?ga=GA1.1.1334458544.1722150011&semt=sph",
|
||||||
|
"https://img.freepik.com/premium-photo/motorcycle-vehicle-3d-modelling_274824-502.jpg?ga=GA1.1.1334458544.1722150011&semt=sph",
|
||||||
|
"https://t3.ftcdn.net/jpg/01/68/26/06/240_F_168260687_UfaDjjs6TxcIB6BdsquSeCmYWEFmN1Sh.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/03/48/50/34/240_F_348503435_On7Tt5Eqn7IP9QWYTQL0H1smubU8gvLv.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/02/76/70/70/240_F_276707060_WpP9bwHWv0Wdqqn0pEgtSuIgXUvgkbs7.jpg",
|
||||||
|
"https://t3.ftcdn.net/jpg/02/65/43/04/240_F_265430460_DIHqnrziar7WL2rmW0qbDO07TbxjlPQo.jpg"
|
||||||
|
)
|
||||||
|
var followList = emptyList<Pair<Int, Int>>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
val faker = faker {
|
||||||
|
this.fakerConfig {
|
||||||
|
locale = "en"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
accountData = (0..300).toList().mapIndexed { idx, _ ->
|
||||||
|
AccountProfile(
|
||||||
|
id = idx,
|
||||||
|
followerCount = 0,
|
||||||
|
followingCount = 0,
|
||||||
|
nickName = faker.name.name(),
|
||||||
|
avatar = imageList.random(),
|
||||||
|
bio = "I am a software engineer",
|
||||||
|
country = faker.address.country()
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// make a random follow rel
|
||||||
|
for (i in 0..10000) {
|
||||||
|
var person1 = accountData.random()
|
||||||
|
var persion2 = accountData.random()
|
||||||
|
followList += Pair(person1.id, persion2.id)
|
||||||
|
// update followerCount and followingCount
|
||||||
|
accountData = accountData.map {
|
||||||
|
if (it.id == person1.id) {
|
||||||
|
it.copy(followingCount = it.followingCount + 1)
|
||||||
|
} else if (it.id == persion2.id) {
|
||||||
|
it.copy(followerCount = it.followerCount + 1)
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
momentData = (0..300).toList().mapIndexed { idx, _ ->
|
||||||
|
val person = accountData.random()
|
||||||
|
MomentItem(
|
||||||
|
id = idx,
|
||||||
|
avatar = person.avatar,
|
||||||
|
nickname = person.nickName,
|
||||||
|
location = person.country,
|
||||||
|
time = "2023.02.02 11:23",
|
||||||
|
followStatus = false,
|
||||||
|
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
|
||||||
|
momentPicture = R.drawable.default_moment_img,
|
||||||
|
likeCount = faker.random.nextInt(0, 100),
|
||||||
|
commentCount = faker.random.nextInt(0, 100),
|
||||||
|
shareCount = faker.random.nextInt(0, 100),
|
||||||
|
favoriteCount = faker.random.nextInt(0, 100),
|
||||||
|
images = imageList.shuffled().take(3),
|
||||||
|
authorId = person.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,10 +29,12 @@ import com.aiosman.riderpro.ui.gallery.ProfileTimelineScreen
|
|||||||
import com.aiosman.riderpro.ui.index.IndexScreen
|
import com.aiosman.riderpro.ui.index.IndexScreen
|
||||||
import com.aiosman.riderpro.ui.like.LikeScreen
|
import com.aiosman.riderpro.ui.like.LikeScreen
|
||||||
import com.aiosman.riderpro.ui.location.LocationDetailScreen
|
import com.aiosman.riderpro.ui.location.LocationDetailScreen
|
||||||
|
import com.aiosman.riderpro.ui.login.LoginPage
|
||||||
import com.aiosman.riderpro.ui.message.NotificationsScreen
|
import com.aiosman.riderpro.ui.message.NotificationsScreen
|
||||||
import com.aiosman.riderpro.ui.modification.EditModificationScreen
|
import com.aiosman.riderpro.ui.modification.EditModificationScreen
|
||||||
import com.aiosman.riderpro.ui.post.NewPostScreen
|
import com.aiosman.riderpro.ui.post.NewPostScreen
|
||||||
import com.aiosman.riderpro.ui.post.PostScreen
|
import com.aiosman.riderpro.ui.post.PostScreen
|
||||||
|
import com.aiosman.riderpro.ui.profile.AccountProfile
|
||||||
|
|
||||||
sealed class NavigationRoute(
|
sealed class NavigationRoute(
|
||||||
val route: String,
|
val route: String,
|
||||||
@@ -50,6 +52,8 @@ sealed class NavigationRoute(
|
|||||||
data object Followers : NavigationRoute("Followers")
|
data object Followers : NavigationRoute("Followers")
|
||||||
data object NewPost : NavigationRoute("NewPost")
|
data object NewPost : NavigationRoute("NewPost")
|
||||||
data object EditModification : NavigationRoute("EditModification")
|
data object EditModification : NavigationRoute("EditModification")
|
||||||
|
data object Login : NavigationRoute("Login")
|
||||||
|
data object AccountProfile : NavigationRoute("AccountProfile/{id}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -61,7 +65,7 @@ fun NavigationController(navController: NavHostController) {
|
|||||||
|
|
||||||
NavHost(
|
NavHost(
|
||||||
navController = navController,
|
navController = navController,
|
||||||
startDestination = NavigationRoute.Index.route,
|
startDestination = NavigationRoute.Login.route,
|
||||||
) {
|
) {
|
||||||
composable(route = NavigationRoute.Index.route) {
|
composable(route = NavigationRoute.Index.route) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
@@ -134,6 +138,16 @@ fun NavigationController(navController: NavHostController) {
|
|||||||
EditModificationScreen()
|
EditModificationScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
composable(route = NavigationRoute.Login.route) {
|
||||||
|
LoginPage()
|
||||||
|
|
||||||
|
}
|
||||||
|
composable(
|
||||||
|
route = NavigationRoute.AccountProfile.route,
|
||||||
|
arguments = listOf(navArgument("id") { type = NavType.StringType })
|
||||||
|
) {
|
||||||
|
AccountProfile(it.arguments?.getString("id")!!)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,12 +41,10 @@ import androidx.paging.PagingData
|
|||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import com.aiosman.riderpro.ui.post.CommentsSection
|
import com.aiosman.riderpro.ui.post.CommentsSection
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.data.comment.Comment
|
import com.aiosman.riderpro.data.Comment
|
||||||
import com.aiosman.riderpro.data.comment.CommentPagingSource
|
import com.aiosman.riderpro.data.CommentPagingSource
|
||||||
import com.aiosman.riderpro.data.comment.CommentRemoteDataSource
|
import com.aiosman.riderpro.data.CommentRemoteDataSource
|
||||||
import com.aiosman.riderpro.data.comment.TestCommentServiceImpl
|
import com.aiosman.riderpro.data.TestCommentServiceImpl
|
||||||
import com.aiosman.riderpro.model.MomentItem
|
|
||||||
import com.aiosman.riderpro.ui.index.tabs.moment.MomentViewModel.momentListPagingSource
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -50,7 +51,7 @@ fun AnimatedLikeIcon(
|
|||||||
animationSpec = tween(100)
|
animationSpec = tween(100)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.clickable {
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.noRippleClickable {
|
||||||
liked = !liked
|
liked = !liked
|
||||||
onClick?.invoke()
|
onClick?.invoke()
|
||||||
// Trigger shake animation
|
// Trigger shake animation
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ fun StatusBarMask(darkIcons: Boolean = true) {
|
|||||||
fun StatusBarMaskLayout(
|
fun StatusBarMaskLayout(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
darkIcons: Boolean = true,
|
darkIcons: Boolean = true,
|
||||||
|
useNavigationBarMask: Boolean = true,
|
||||||
maskBoxBackgroundColor: Color = Color.Transparent,
|
maskBoxBackgroundColor: Color = Color.Transparent,
|
||||||
content: @Composable ColumnScope.() -> Unit
|
content: @Composable ColumnScope.() -> Unit
|
||||||
) {
|
) {
|
||||||
@@ -57,7 +58,7 @@ fun StatusBarMaskLayout(
|
|||||||
|
|
||||||
}
|
}
|
||||||
content()
|
content()
|
||||||
if (navigationBarPaddings > 24.dp) {
|
if (navigationBarPaddings > 24.dp && useNavigationBarMask) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(navigationBarPaddings).fillMaxWidth().background(Color.White)
|
.height(navigationBarPaddings).fillMaxWidth().background(Color.White)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -46,51 +47,43 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.aiosman.riderpro.LocalAnimatedContentScope
|
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.LocalSharedTransitionScope
|
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.model.MomentItem
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
|
import com.aiosman.riderpro.ui.NavigationRoute
|
||||||
import com.aiosman.riderpro.ui.comment.CommentModalContent
|
import com.aiosman.riderpro.ui.comment.CommentModalContent
|
||||||
import com.aiosman.riderpro.ui.composables.AnimatedCounter
|
import com.aiosman.riderpro.ui.composables.AnimatedCounter
|
||||||
import com.aiosman.riderpro.ui.composables.AnimatedLikeIcon
|
import com.aiosman.riderpro.ui.composables.AnimatedLikeIcon
|
||||||
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
private val DATA = (0..60).toList().mapIndexed { idx, _ ->
|
|
||||||
MomentItem(
|
|
||||||
id = idx,
|
|
||||||
avatar = R.drawable.default_avatar,
|
|
||||||
nickname = "Onyama Limba",
|
|
||||||
location = "Japan",
|
|
||||||
time = "2023.02.02 11:23",
|
|
||||||
followStatus = false,
|
|
||||||
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
|
|
||||||
momentPicture = R.drawable.default_moment_img,
|
|
||||||
likeCount = 21,
|
|
||||||
commentCount = 43,
|
|
||||||
shareCount = 33,
|
|
||||||
favoriteCount = 211
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentsList() {
|
fun MomentsList() {
|
||||||
val model = MomentViewModel
|
val model = MomentViewModel
|
||||||
val moments = model.momentsFlow.collectAsLazyPagingItems()
|
var dataFlow = model.momentsFlow
|
||||||
|
var moments = dataFlow.collectAsLazyPagingItems()
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
items(moments.itemCount) { idx ->
|
items(moments.itemCount) { idx ->
|
||||||
val momentItem = moments[idx] ?: return@items
|
val momentItem = moments[idx] ?: return@items
|
||||||
MomentCard(momentItem = momentItem)
|
MomentCard(momentItem = momentItem, onLikeClick = {
|
||||||
|
scope.launch {
|
||||||
|
model.likeMoment(momentItem.id)
|
||||||
|
moments.refresh()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentCard(
|
fun MomentCard(
|
||||||
momentItem: MomentItem,
|
momentItem: MomentItem,
|
||||||
|
onLikeClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
Column(
|
Column(
|
||||||
@@ -100,18 +93,17 @@ fun MomentCard(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable {
|
.noRippleClickable {
|
||||||
navController.navigate("Post/${momentItem.id}")
|
navController.navigate("Post/${momentItem.id}")
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
MomentContentGroup(momentItem = momentItem)
|
MomentContentGroup(momentItem = momentItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
val momentOperateBtnBoxModifier = Modifier
|
val momentOperateBtnBoxModifier = Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
ModificationListHeader()
|
ModificationListHeader()
|
||||||
MomentBottomOperateRowGroup(momentOperateBtnBoxModifier, momentItem = momentItem)
|
MomentBottomOperateRowGroup(momentOperateBtnBoxModifier, momentItem = momentItem, onLikeClick = onLikeClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,14 +205,19 @@ fun MomentPostTime(time: String) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentTopRowGroup(momentItem: MomentItem) {
|
fun MomentTopRowGroup(momentItem: MomentItem) {
|
||||||
|
val navController = LocalNavController.current
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(40.dp)
|
.height(40.dp)
|
||||||
.padding(top = 0.dp, bottom = 0.dp, start = 24.dp, end = 24.dp)
|
.padding(top = 0.dp, bottom = 0.dp, start = 24.dp, end = 24.dp)
|
||||||
) {
|
) {
|
||||||
Image(
|
AsyncImage(
|
||||||
painter = painterResource(id = momentItem.avatar),
|
momentItem.avatar,
|
||||||
contentDescription = ""
|
contentDescription = "",
|
||||||
|
modifier = Modifier.size(40.dp).noRippleClickable {
|
||||||
|
navController.navigate(NavigationRoute.AccountProfile.route.replace("{id}", momentItem.authorId.toString()))
|
||||||
|
},
|
||||||
|
contentScale = ContentScale.Crop
|
||||||
)
|
)
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -254,8 +251,6 @@ fun MomentTopRowGroup(momentItem: MomentItem) {
|
|||||||
fun MomentContentGroup(
|
fun MomentContentGroup(
|
||||||
momentItem: MomentItem,
|
momentItem: MomentItem,
|
||||||
) {
|
) {
|
||||||
// val sharedTransitionScope = LocalSharedTransitionScope.current
|
|
||||||
// val animatedContentScope = LocalAnimatedContentScope.current
|
|
||||||
val displayImageUrl = momentItem.images.firstOrNull()
|
val displayImageUrl = momentItem.images.firstOrNull()
|
||||||
Text(
|
Text(
|
||||||
text = momentItem.momentTextContent,
|
text = momentItem.momentTextContent,
|
||||||
@@ -312,7 +307,11 @@ fun MomentOperateBtn(count: String, content: @Composable () -> Unit) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentBottomOperateRowGroup(modifier: Modifier, momentItem: MomentItem) {
|
fun MomentBottomOperateRowGroup(
|
||||||
|
modifier: Modifier,
|
||||||
|
onLikeClick: () -> Unit = {},
|
||||||
|
momentItem: MomentItem
|
||||||
|
) {
|
||||||
var systemUiController = rememberSystemUiController()
|
var systemUiController = rememberSystemUiController()
|
||||||
var showCommentModal by remember { mutableStateOf(false) }
|
var showCommentModal by remember { mutableStateOf(false) }
|
||||||
if (showCommentModal) {
|
if (showCommentModal) {
|
||||||
@@ -340,10 +339,7 @@ fun MomentBottomOperateRowGroup(modifier: Modifier, momentItem: MomentItem) {
|
|||||||
) {
|
) {
|
||||||
MomentOperateBtn(count = momentItem.likeCount.toString()) {
|
MomentOperateBtn(count = momentItem.likeCount.toString()) {
|
||||||
AnimatedLikeIcon(modifier = Modifier.size(24.dp)) {
|
AnimatedLikeIcon(modifier = Modifier.size(24.dp)) {
|
||||||
MomentViewModel.updateById(
|
onLikeClick()
|
||||||
momentItem.id,
|
|
||||||
momentItem.copy(likeCount = momentItem.likeCount + 1)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -356,19 +352,19 @@ fun MomentBottomOperateRowGroup(modifier: Modifier, momentItem: MomentItem) {
|
|||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
MomentOperateBtn(icon = R.drawable.rider_pro_moment_comment, count = "43")
|
MomentOperateBtn(icon = R.drawable.rider_pro_moment_comment, count = momentItem.commentCount.toString())
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
MomentOperateBtn(icon = R.drawable.rider_pro_share, count = "33")
|
MomentOperateBtn(icon = R.drawable.rider_pro_share, count = momentItem.shareCount.toString())
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
MomentOperateBtn(icon = R.drawable.rider_pro_favoriate, count = "211")
|
MomentOperateBtn(icon = R.drawable.rider_pro_favoriate, count = momentItem.favoriteCount.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,52 +8,32 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.paging.Pager
|
import androidx.paging.Pager
|
||||||
import androidx.paging.PagingConfig
|
import androidx.paging.PagingConfig
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
import androidx.paging.cachedIn
|
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.data.moment.MomentPagingSource
|
import com.aiosman.riderpro.data.MomentPagingSource
|
||||||
import com.aiosman.riderpro.data.moment.MomentRemoteDataSource
|
import com.aiosman.riderpro.data.MomentRemoteDataSource
|
||||||
import com.aiosman.riderpro.data.moment.TestMomentServiceImpl
|
import com.aiosman.riderpro.data.MomentService
|
||||||
|
import com.aiosman.riderpro.data.TestMomentServiceImpl
|
||||||
import com.aiosman.riderpro.model.MomentItem
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
private val DATA = (0..60).toList().mapIndexed { idx, _ ->
|
|
||||||
MomentItem(
|
|
||||||
id = idx,
|
|
||||||
avatar = R.drawable.default_avatar,
|
|
||||||
nickname = "Onyama Limba",
|
|
||||||
location = "Japan",
|
|
||||||
time = "2023.02.02 11:23",
|
|
||||||
followStatus = false,
|
|
||||||
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
|
|
||||||
momentPicture = R.drawable.default_moment_img,
|
|
||||||
likeCount = 21,
|
|
||||||
commentCount = 43,
|
|
||||||
shareCount = 33,
|
|
||||||
favoriteCount = 211
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
object MomentViewModel : ViewModel() {
|
object MomentViewModel : ViewModel() {
|
||||||
var momentList by mutableStateOf(DATA)
|
val momentService: MomentService = TestMomentServiceImpl()
|
||||||
|
|
||||||
fun updateById(id: Int, momentItem: MomentItem) {
|
|
||||||
momentList = momentList.map {
|
|
||||||
if (it.id == id) {
|
|
||||||
momentItem
|
|
||||||
} else {
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}.toMutableStateList()
|
|
||||||
}
|
|
||||||
|
|
||||||
var momentListPagingSource = MomentPagingSource(
|
var momentListPagingSource = MomentPagingSource(
|
||||||
MomentRemoteDataSource(TestMomentServiceImpl())
|
MomentRemoteDataSource(momentService)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
var momentsFlow: Flow<PagingData<MomentItem>> = Pager(
|
||||||
val momentsFlow: Flow<PagingData<MomentItem>> = Pager(
|
|
||||||
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
pagingSourceFactory = { momentListPagingSource }
|
pagingSourceFactory = {
|
||||||
|
MomentPagingSource(
|
||||||
|
MomentRemoteDataSource(momentService)
|
||||||
|
)
|
||||||
|
}
|
||||||
).flow
|
).flow
|
||||||
|
|
||||||
|
suspend fun likeMoment(id: Int) {
|
||||||
|
momentService.likeMoment(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.aiosman.riderpro.ui.index.tabs.profile
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import com.aiosman.riderpro.data.AccountProfile
|
||||||
|
import com.aiosman.riderpro.data.AccountService
|
||||||
|
import com.aiosman.riderpro.data.TestAccountServiceImpl
|
||||||
|
import com.aiosman.riderpro.data.MomentPagingSource
|
||||||
|
import com.aiosman.riderpro.data.MomentRemoteDataSource
|
||||||
|
import com.aiosman.riderpro.data.TestMomentServiceImpl
|
||||||
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
object MyProfileViewModel {
|
||||||
|
val service: AccountService = TestAccountServiceImpl()
|
||||||
|
var profile by mutableStateOf<AccountProfile?>(null)
|
||||||
|
suspend fun loadProfile() {
|
||||||
|
profile = service.getAccountProfile()
|
||||||
|
}
|
||||||
|
var momentListPagingSource = MomentPagingSource(
|
||||||
|
MomentRemoteDataSource(TestMomentServiceImpl())
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
val momentsFlow: Flow<PagingData<MomentItem>> = Pager(
|
||||||
|
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
|
pagingSourceFactory = { momentListPagingSource }
|
||||||
|
).flow
|
||||||
|
val followerCount get() = profile?.followerCount ?: 0
|
||||||
|
val followingCount get() = profile?.followingCount ?: 0
|
||||||
|
val bio get() = profile?.bio ?: ""
|
||||||
|
val nickName get() = profile?.nickName ?: ""
|
||||||
|
val avatar get() = profile?.avatar
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,46 +16,66 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.widthIn
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import coil.compose.AsyncImage
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
|
import com.aiosman.riderpro.data.AccountProfile
|
||||||
import com.aiosman.riderpro.model.MomentItem
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
import com.aiosman.riderpro.model.profileMomentItems
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProfilePage(){
|
fun ProfilePage() {
|
||||||
Column (
|
val model = MyProfileViewModel
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
model.loadProfile()
|
||||||
|
}
|
||||||
|
val profile = model.momentsFlow.collectAsLazyPagingItems()
|
||||||
|
LazyColumn(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
|
||||||
.padding(bottom = 16.dp),
|
.padding(bottom = 16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Top,
|
verticalArrangement = Arrangement.Top,
|
||||||
){
|
) {
|
||||||
|
item {
|
||||||
CarGroup()
|
CarGroup()
|
||||||
UserInformation()
|
model.profile?.let {
|
||||||
|
UserInformation(accountProfile = it)
|
||||||
|
}
|
||||||
|
|
||||||
RidingStyle()
|
RidingStyle()
|
||||||
UserMoment()
|
}
|
||||||
|
items(profile.itemCount) { idx ->
|
||||||
|
val momentItem = profile[idx] ?: return@items
|
||||||
|
MomentPostUnit(momentItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CarGroup(){
|
fun CarGroup() {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -68,144 +88,271 @@ fun CarGroup(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CarTopInformation(){
|
fun CarTopInformation() {
|
||||||
Row{
|
Row {
|
||||||
Text(text = "BMW", color = Color.Black, fontSize = 12.sp, style = TextStyle(fontWeight = FontWeight.Bold))
|
Text(
|
||||||
Text(modifier = Modifier.padding(start = 4.dp), text = "/", color = Color.Gray, fontSize = 12.sp)
|
text = "BMW",
|
||||||
Text(modifier = Modifier.padding(start = 4.dp), text = "M1000RR", color = Color.Gray, fontSize = 12.sp)
|
color = Color.Black,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(start = 4.dp),
|
||||||
|
text = "/",
|
||||||
|
color = Color.Gray,
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(start = 4.dp),
|
||||||
|
text = "M1000RR",
|
||||||
|
color = Color.Gray,
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CarTopPicture(){
|
fun CarTopPicture() {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(width = 336.dp, height = 224.dp)
|
.size(width = 336.dp, height = 224.dp)
|
||||||
.padding(top = 42.dp),
|
.padding(top = 42.dp),
|
||||||
painter = painterResource(id = R.drawable.default_profile_moto), contentDescription = "")
|
painter = painterResource(id = R.drawable.default_profile_moto), contentDescription = ""
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserInformation(){
|
fun UserInformation(isSelf: Boolean = true,accountProfile: AccountProfile) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(top = 8.dp, start = 33.dp, end = 33.dp),
|
.padding(top = 8.dp, start = 33.dp, end = 33.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally){
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
Row (modifier = Modifier.fillMaxWidth()){
|
) {
|
||||||
|
Row(modifier = Modifier.fillMaxWidth()) {
|
||||||
val userInfoModifier = Modifier.weight(1f)
|
val userInfoModifier = Modifier.weight(1f)
|
||||||
UserInformationFollowers(userInfoModifier)
|
UserInformationFollowers(userInfoModifier,accountProfile)
|
||||||
UserInformationBasic(userInfoModifier)
|
UserInformationBasic(userInfoModifier,accountProfile)
|
||||||
UserInformationFollowing(userInfoModifier)
|
UserInformationFollowing(userInfoModifier,accountProfile)
|
||||||
}
|
}
|
||||||
UserInformationSlogan()
|
UserInformationSlogan()
|
||||||
CommunicationOperatorGroup()
|
CommunicationOperatorGroup(isSelf = isSelf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserInformationFollowers(modifier: Modifier){
|
fun UserInformationFollowers(modifier: Modifier,accountProfile: AccountProfile) {
|
||||||
Column(modifier = modifier.padding(top = 31.dp)) {
|
Column(modifier = modifier.padding(top = 31.dp)) {
|
||||||
Text(modifier = Modifier.padding(bottom = 5.dp),text = "183", fontSize = 24.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
Text(
|
||||||
|
modifier = Modifier.padding(bottom = 5.dp),
|
||||||
|
text = accountProfile.followerCount.toString(),
|
||||||
|
fontSize = 24.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
Spacer(
|
Spacer(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(width = 88.83.dp, height = 1.dp)
|
.size(width = 88.83.dp, height = 1.dp)
|
||||||
.border(width = 1.dp, color = Color.Gray)
|
.border(width = 1.dp, color = Color.Gray)
|
||||||
.padding(top = 5.dp, bottom = 5.dp)
|
.padding(top = 5.dp, bottom = 5.dp)
|
||||||
)
|
)
|
||||||
Text(modifier = Modifier.padding(top = 5.dp),text = "FOLLOWERS", fontSize = 12.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
Text(
|
||||||
|
modifier = Modifier.padding(top = 5.dp),
|
||||||
|
text = "FOLLOWERS",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserInformationBasic(modifier: Modifier){
|
fun UserInformationBasic(modifier: Modifier,accountProfile: AccountProfile) {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally) {
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
Box(modifier = Modifier.size(width = 112.dp, height = 112.dp),
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.size(width = 112.dp, height = 112.dp),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
){
|
) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
painter = painterResource(id = R.drawable.avatar_bold), contentDescription = "")
|
painter = painterResource(id = R.drawable.avatar_bold), contentDescription = ""
|
||||||
Image(
|
)
|
||||||
|
AsyncImage(
|
||||||
|
accountProfile.avatar,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(width = 88.dp, height = 88.dp)
|
.size(width = 88.dp, height = 88.dp)
|
||||||
.clip(
|
.clip(
|
||||||
RoundedCornerShape(88.dp)
|
RoundedCornerShape(88.dp)
|
||||||
),
|
),
|
||||||
painter = painterResource(id = R.drawable.default_avatar), contentDescription = "")
|
contentDescription = "",
|
||||||
|
contentScale = ContentScale.Crop
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
Text(modifier = Modifier.padding(top = 8.dp), text = "Atom", fontSize = 32.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
Text(
|
||||||
Text(modifier = Modifier.padding(top = 4.dp), text = "America", fontSize = 12.sp, color = Color.Gray)
|
modifier = Modifier.widthIn(max =220.dp).padding(top = 8.dp),
|
||||||
Text(modifier = Modifier.padding(top = 4.dp), text = "Member since Jun 4.2019", fontSize = 12.sp, color = Color.Gray)
|
text = accountProfile.nickName,
|
||||||
|
fontSize = 32.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(top = 4.dp),
|
||||||
|
text = accountProfile.country,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color.Gray
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(top = 4.dp),
|
||||||
|
text = "Member since Jun 4.2019",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color.Gray
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserInformationFollowing(modifier: Modifier){
|
fun UserInformationFollowing(modifier: Modifier,accountProfile: AccountProfile) {
|
||||||
Column(modifier = modifier.padding(top = 6.dp),
|
Column(
|
||||||
horizontalAlignment = Alignment.End) {
|
modifier = modifier.padding(top = 6.dp),
|
||||||
Text(modifier = Modifier.padding(bottom = 5.dp), text = "306", fontSize = 24.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
horizontalAlignment = Alignment.End
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(bottom = 5.dp),
|
||||||
|
text = accountProfile.followingCount.toString(),
|
||||||
|
fontSize = 24.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(width = 88.83.dp, height = 1.dp)
|
.size(width = 88.83.dp, height = 1.dp)
|
||||||
.border(width = 1.dp, color = Color.Gray)
|
.border(width = 1.dp, color = Color.Gray)
|
||||||
|
|
||||||
)
|
)
|
||||||
Text(modifier = Modifier.padding(top = 5.dp),text = "FOLLOWING", fontSize = 12.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
Text(
|
||||||
|
modifier = Modifier.padding(top = 5.dp),
|
||||||
|
text = "FOLLOWING",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserInformationSlogan(){
|
fun UserInformationSlogan() {
|
||||||
Text(modifier = Modifier.padding(top = 23.dp),text = "Ridering shooting fishing not much more", fontSize = 13.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
val model = MyProfileViewModel
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(top = 23.dp),
|
||||||
|
text = model.bio,
|
||||||
|
fontSize = 13.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationOperatorGroup(){
|
fun CommunicationOperatorGroup(isSelf: Boolean = true) {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
Row (modifier = Modifier
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(top = 16.dp), horizontalArrangement = Arrangement.Center){
|
.padding(top = 16.dp), horizontalArrangement = Arrangement.Center
|
||||||
Box(modifier = Modifier.size(width = 142.dp, height = 40.dp),
|
) {
|
||||||
contentAlignment = Alignment.Center){
|
Box(
|
||||||
Image(modifier = Modifier.fillMaxSize(), painter = painterResource(id = R.drawable.rider_pro_profile_follow), contentDescription = "")
|
modifier = Modifier.size(width = 142.dp, height = 40.dp),
|
||||||
Text(text = "FOLLOW", fontSize = 16.sp, color = Color.White, style = TextStyle(fontWeight = FontWeight.Bold))
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_profile_follow),
|
||||||
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "FOLLOW",
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = Color.White,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Box(modifier = Modifier
|
if (isSelf) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
.size(width = 142.dp, height = 40.dp)
|
.size(width = 142.dp, height = 40.dp)
|
||||||
.padding(start = 6.dp).clickable {
|
.padding(start = 6.dp)
|
||||||
|
.clickable {
|
||||||
navController.navigate("MyMessage")
|
navController.navigate("MyMessage")
|
||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center){
|
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))
|
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 {
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(width = 142.dp, height = 40.dp)
|
||||||
|
.clickable {
|
||||||
navController.navigate("ProfileTimeline")
|
navController.navigate("ProfileTimeline")
|
||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center){
|
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))
|
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)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun RidingStyle(){
|
fun RidingStyle() {
|
||||||
Column(modifier = Modifier
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 24.dp, top = 40.dp, end = 24.dp),
|
.padding(start = 24.dp, top = 40.dp, end = 24.dp),
|
||||||
horizontalAlignment = Alignment.Start) {
|
horizontalAlignment = Alignment.Start
|
||||||
Text(text = "RIDING STYLES", fontSize = 18.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
) {
|
||||||
Image(modifier = Modifier
|
Text(
|
||||||
|
text = "RIDING STYLES",
|
||||||
|
fontSize = 18.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
|
Image(
|
||||||
|
modifier = Modifier
|
||||||
.padding(top = 4.dp)
|
.padding(top = 4.dp)
|
||||||
.height(8.dp),painter = painterResource(id = R.drawable.rider_pro_profile_line), contentDescription = "")
|
.height(8.dp),
|
||||||
FlowRow (modifier = Modifier
|
painter = painterResource(id = R.drawable.rider_pro_profile_line),
|
||||||
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
FlowRow(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(top = 24.dp)){
|
.padding(top = 24.dp)
|
||||||
|
) {
|
||||||
RidingStyleItem(styleContent = "Cruiser")
|
RidingStyleItem(styleContent = "Cruiser")
|
||||||
RidingStyleItem(styleContent = "Bobber")
|
RidingStyleItem(styleContent = "Bobber")
|
||||||
RidingStyleItem(styleContent = "Cafe")
|
RidingStyleItem(styleContent = "Cafe")
|
||||||
@@ -219,100 +366,150 @@ fun RidingStyle(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RidingStyleItem(styleContent: String){
|
fun RidingStyleItem(styleContent: String) {
|
||||||
Box(modifier = Modifier.padding(bottom = 8.dp, end = 8.dp),
|
Box(
|
||||||
contentAlignment = Alignment.Center) {
|
modifier = Modifier.padding(bottom = 8.dp, end = 8.dp),
|
||||||
Image(modifier = Modifier.shadow(
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
modifier = Modifier.shadow(
|
||||||
ambientColor = Color.Gray,
|
ambientColor = Color.Gray,
|
||||||
spotColor = Color(0f,0f,0f,0.2f),
|
spotColor = Color(0f, 0f, 0f, 0.2f),
|
||||||
elevation = 20.dp,
|
elevation = 20.dp,
|
||||||
), painter = painterResource(id = R.drawable.rider_pro_style_wrapper), contentDescription = "")
|
),
|
||||||
Text(modifier = Modifier.padding(start = 5.dp, end = 5.dp), text = styleContent, fontSize = 12.sp, color = Color.Gray, style = TextStyle(fontWeight = FontWeight.Bold))
|
painter = painterResource(id = R.drawable.rider_pro_style_wrapper),
|
||||||
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(start = 5.dp, end = 5.dp),
|
||||||
|
text = styleContent,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color.Gray,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserMoment(){
|
fun UserMoment(scope: LazyListScope) {
|
||||||
profileMomentItems.forEach(
|
|
||||||
action = { MomentPostUnit(it) }
|
|
||||||
|
// LazyColumn(
|
||||||
|
// modifier = Modifier
|
||||||
|
// .fillMaxWidth()
|
||||||
|
// .weight(1f)
|
||||||
|
// ){
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MomentPostUnit(momentItem: MomentItem) {
|
||||||
|
TimeGroup(momentItem.time)
|
||||||
|
MomentCard(
|
||||||
|
momentItem.momentTextContent,
|
||||||
|
momentItem.momentPicture,
|
||||||
|
momentItem.likeCount.toString(),
|
||||||
|
momentItem.commentCount.toString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentPostUnit(momentItem: MomentItem){
|
fun TimeGroup(time: String = "2024.06.08 12:23") {
|
||||||
TimeGroup(momentItem.time)
|
Row(
|
||||||
MomentCard(momentItem.momentTextContent,
|
modifier = Modifier
|
||||||
momentItem.momentPicture,
|
|
||||||
momentItem.likeCount.toString(),
|
|
||||||
momentItem.commentCount.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun TimeGroup(time: String = "2024.06.08 12:23"){
|
|
||||||
Row(modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 24.dp, top = 40.dp, end = 24.dp),
|
.padding(start = 24.dp, top = 40.dp, end = 24.dp),
|
||||||
horizontalArrangement = Arrangement.Start,
|
horizontalArrangement = Arrangement.Start,
|
||||||
verticalAlignment = Alignment.CenterVertically){
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.padding(end = 12.dp),
|
modifier = Modifier.padding(end = 12.dp),
|
||||||
painter = painterResource(id = R.drawable.rider_pro_moment_time_flag), contentDescription = "")
|
painter = painterResource(id = R.drawable.rider_pro_moment_time_flag),
|
||||||
Text(text = time,fontSize = 22.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold))
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = time,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentCard(content: String,@DrawableRes picture: Int, like: String, comment: String){
|
fun MomentCard(content: String, @DrawableRes picture: Int, like: String, comment: String) {
|
||||||
Column(modifier = Modifier
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 48.dp, top = 18.dp, end = 24.dp)
|
.padding(start = 48.dp, top = 18.dp, end = 24.dp)
|
||||||
.border(width = 1.dp, color = Color(0f,0f,0f,0.1f), shape = RoundedCornerShape(6.dp))
|
.border(width = 1.dp, color = Color(0f, 0f, 0f, 0.1f), shape = RoundedCornerShape(6.dp))
|
||||||
){
|
) {
|
||||||
MomentCardTopContent(content)
|
MomentCardTopContent(content)
|
||||||
MomentCardPicture(picture)
|
MomentCardPicture(picture)
|
||||||
MomentCardOperation(like,comment)
|
MomentCardOperation(like, comment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentCardTopContent(content: String){
|
fun MomentCardTopContent(content: String) {
|
||||||
Row(modifier = Modifier
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Start,
|
horizontalArrangement = Arrangement.Start,
|
||||||
verticalAlignment = Alignment.CenterVertically){
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(16.dp),
|
modifier = Modifier.padding(16.dp),
|
||||||
text = content,fontSize = 16.sp, color = Color.Black)
|
text = content, fontSize = 16.sp, color = Color.Black
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentCardPicture(@DrawableRes drawable: Int){
|
fun MomentCardPicture(@DrawableRes drawable: Int) {
|
||||||
Image(modifier = Modifier
|
Image(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(16.dp), painter = painterResource(id = drawable), contentDescription = "")
|
.padding(16.dp), painter = painterResource(id = drawable), contentDescription = ""
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentCardOperation(like: String, comment: String){
|
fun MomentCardOperation(like: String, comment: String) {
|
||||||
Row(modifier = Modifier
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(56.dp),
|
.height(56.dp),
|
||||||
horizontalArrangement = Arrangement.Start,
|
horizontalArrangement = Arrangement.Start,
|
||||||
verticalAlignment = Alignment.CenterVertically){
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
MomentCardOperationItem(drawable = R.drawable.rider_pro_like, number = like, modifier = Modifier.weight(1f))
|
MomentCardOperationItem(
|
||||||
MomentCardOperationItem(drawable = R.drawable.rider_pro_moment_comment, number = comment, modifier = Modifier.weight(1f))
|
drawable = R.drawable.rider_pro_like,
|
||||||
|
number = like,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
MomentCardOperationItem(
|
||||||
|
drawable = R.drawable.rider_pro_moment_comment,
|
||||||
|
number = comment,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentCardOperationItem(@DrawableRes drawable: Int, number: String, modifier: Modifier){
|
fun MomentCardOperationItem(@DrawableRes drawable: Int, number: String, modifier: Modifier) {
|
||||||
Row(modifier = modifier,
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically){
|
modifier = modifier,
|
||||||
Image(modifier = Modifier.padding(start = 16.dp, end = 8.dp),
|
verticalAlignment = Alignment.CenterVertically
|
||||||
painter = painterResource(id = drawable), contentDescription = "")
|
) {
|
||||||
|
Image(
|
||||||
|
modifier = Modifier.padding(start = 16.dp, end = 8.dp),
|
||||||
|
painter = painterResource(id = drawable), contentDescription = ""
|
||||||
|
)
|
||||||
Text(text = number)
|
Text(text = number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
41
app/src/main/java/com/aiosman/riderpro/ui/login/login.kt
Normal file
41
app/src/main/java/com/aiosman/riderpro/ui/login/login.kt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package com.aiosman.riderpro.ui.login
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.ElevatedButton
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.aiosman.riderpro.LocalNavController
|
||||||
|
import com.aiosman.riderpro.ui.NavigationRoute
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoginPage() {
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
navController.navigate(NavigationRoute.Index.route)
|
||||||
|
}
|
||||||
|
Scaffold { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(paddingValues).padding(horizontal = 16.dp).fillMaxSize(),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text("Login", fontSize = 24.sp)
|
||||||
|
ElevatedButton(
|
||||||
|
onClick = { /*TODO*/ },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text("Login with Google")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,10 +19,10 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.layout.wrapContentWidth
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
@@ -64,18 +64,15 @@ import androidx.paging.PagingData
|
|||||||
import androidx.paging.compose.LazyPagingItems
|
import androidx.paging.compose.LazyPagingItems
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.aiosman.riderpro.LocalAnimatedContentScope
|
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.LocalSharedTransitionScope
|
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.data.comment.Comment
|
import com.aiosman.riderpro.data.Comment
|
||||||
import com.aiosman.riderpro.data.comment.CommentPagingSource
|
import com.aiosman.riderpro.data.CommentPagingSource
|
||||||
import com.aiosman.riderpro.data.comment.CommentRemoteDataSource
|
import com.aiosman.riderpro.data.CommentRemoteDataSource
|
||||||
import com.aiosman.riderpro.data.comment.TestCommentServiceImpl
|
import com.aiosman.riderpro.data.TestCommentServiceImpl
|
||||||
import com.aiosman.riderpro.data.moment.MomentService
|
import com.aiosman.riderpro.data.MomentService
|
||||||
import com.aiosman.riderpro.data.moment.TestMomentServiceImpl
|
import com.aiosman.riderpro.data.TestMomentServiceImpl
|
||||||
import com.aiosman.riderpro.model.MomentItem
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
import com.aiosman.riderpro.ui.comment.CommentModalContent
|
|
||||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||||
import com.aiosman.riderpro.ui.composables.EditCommentBottomModal
|
import com.aiosman.riderpro.ui.composables.EditCommentBottomModal
|
||||||
@@ -122,7 +119,11 @@ fun PostScreen(
|
|||||||
Column(modifier = Modifier.animateContentSize()) {
|
Column(modifier = Modifier.animateContentSize()) {
|
||||||
AnimatedVisibility(visible = showCollapseContent) {
|
AnimatedVisibility(visible = showCollapseContent) {
|
||||||
// collapse content
|
// collapse content
|
||||||
Column {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -267,19 +268,26 @@ fun PostDetails(
|
|||||||
postId: String,
|
postId: String,
|
||||||
momentItem: MomentItem?
|
momentItem: MomentItem?
|
||||||
) {
|
) {
|
||||||
momentItem?.let {
|
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight()
|
||||||
|
) {
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = momentItem.momentTextContent,
|
text = momentItem?.momentTextContent ?:"",
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
)
|
)
|
||||||
Text(text = "12-11 发布")
|
Text(text = "12-11 发布")
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(text = "共231条评论")
|
Text(text = "共231条评论")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.aiosman.riderpro.ui.profile
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import com.aiosman.riderpro.data.AccountProfile
|
||||||
|
import com.aiosman.riderpro.data.MomentPagingSource
|
||||||
|
import com.aiosman.riderpro.data.MomentRemoteDataSource
|
||||||
|
import com.aiosman.riderpro.data.TestMomentServiceImpl
|
||||||
|
import com.aiosman.riderpro.data.TestUserServiceImpl
|
||||||
|
import com.aiosman.riderpro.data.UserService
|
||||||
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
|
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||||
|
import com.aiosman.riderpro.ui.index.tabs.profile.CarGroup
|
||||||
|
import com.aiosman.riderpro.ui.index.tabs.profile.MomentPostUnit
|
||||||
|
import com.aiosman.riderpro.ui.index.tabs.profile.RidingStyle
|
||||||
|
import com.aiosman.riderpro.ui.index.tabs.profile.UserInformation
|
||||||
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AccountProfile(id:String) {
|
||||||
|
// val model = MyProfileViewModel
|
||||||
|
val userService: UserService = TestUserServiceImpl()
|
||||||
|
var userProfile by remember { mutableStateOf<AccountProfile?>(null) }
|
||||||
|
var momentListPagingSource = MomentPagingSource(
|
||||||
|
MomentRemoteDataSource(TestMomentServiceImpl())
|
||||||
|
)
|
||||||
|
val momentsFlow: Flow<PagingData<MomentItem>> = Pager(
|
||||||
|
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
|
pagingSourceFactory = { momentListPagingSource }
|
||||||
|
).flow
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
userProfile = userService.getUserProfile(id)
|
||||||
|
}
|
||||||
|
val items = momentsFlow.collectAsLazyPagingItems()
|
||||||
|
val systemUiController = rememberSystemUiController()
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
systemUiController.setNavigationBarColor(
|
||||||
|
color = androidx.compose.ui.graphics.Color.Transparent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
StatusBarMaskLayout(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
useNavigationBarMask = false
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(bottom = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Top,
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
CarGroup()
|
||||||
|
userProfile?.let {
|
||||||
|
UserInformation(isSelf = false, accountProfile = it)
|
||||||
|
|
||||||
|
}
|
||||||
|
RidingStyle()
|
||||||
|
}
|
||||||
|
items(items.itemCount) { idx ->
|
||||||
|
val momentItem = items[idx] ?: return@items
|
||||||
|
MomentPostUnit(momentItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package com.aiosman.riderpro.ui.profile
|
||||||
|
|
||||||
|
object AccountProfileViewModel {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user