更改目录结构
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
package com.aiosman.riderpro
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
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 HomeViewModel : ViewModel() {
|
||||
val momentList = DATA
|
||||
}
|
||||
@@ -1,22 +1,16 @@
|
||||
package com.aiosman.riderpro
|
||||
|
||||
import ModificationListScreen
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.animation.AnimatedContentScope
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.SharedTransitionLayout
|
||||
import androidx.compose.animation.SharedTransitionScope
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -27,27 +21,18 @@ import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationBarItemColors
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import com.aiosman.riderpro.ui.theme.RiderProTheme
|
||||
import com.aiosman.riderpro.ui.Navigation
|
||||
import com.aiosman.riderpro.ui.index.NavigationItem
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.google.android.libraries.places.api.Places
|
||||
|
||||
@@ -79,98 +64,6 @@ val LocalAnimatedContentScope = compositionLocalOf<AnimatedContentScope> {
|
||||
error("AnimatedContentScope not provided")
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@Composable
|
||||
fun NavigationController(navController: NavHostController) {
|
||||
val navigationBarHeight = with(LocalDensity.current) {
|
||||
WindowInsets.navigationBars.getBottom(this).toDp()
|
||||
}
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = "Index",
|
||||
) {
|
||||
composable(route = "Index") {
|
||||
CompositionLocalProvider(
|
||||
LocalAnimatedContentScope provides this,
|
||||
) {
|
||||
ScaffoldWithNavigationBar2()
|
||||
}
|
||||
}
|
||||
composable(route = "ProfileTimeline") {
|
||||
GalleryPage()
|
||||
}
|
||||
composable(route = "LocationDetail") {
|
||||
Box(
|
||||
modifier = Modifier.padding(bottom = navigationBarHeight)
|
||||
) {
|
||||
LocationDetail()
|
||||
}
|
||||
}
|
||||
composable(route = "OfficialPhoto") {
|
||||
OfficialGalleryPage()
|
||||
}
|
||||
composable(route = "OfficialPhotographer") {
|
||||
OfficialPhotographer()
|
||||
}
|
||||
composable(
|
||||
route = "Post/{id}",
|
||||
arguments = listOf(navArgument("id") { type = NavType.StringType })
|
||||
) { backStackEntry ->
|
||||
CompositionLocalProvider(
|
||||
LocalAnimatedContentScope provides this,
|
||||
) {
|
||||
val id = backStackEntry.arguments?.getString("id")
|
||||
PostPage(
|
||||
id!!
|
||||
)
|
||||
}
|
||||
}
|
||||
composable(route = "ModificationList") {
|
||||
ModificationListScreen()
|
||||
}
|
||||
composable(route = "MyMessage") {
|
||||
NotificationsScreen()
|
||||
}
|
||||
composable(route = "Comments") {
|
||||
CommentsScreen()
|
||||
}
|
||||
composable(route = "Likes") {
|
||||
LikePage()
|
||||
}
|
||||
composable(route = "Followers") {
|
||||
FollowerPage()
|
||||
}
|
||||
composable(route = "NewPost") {
|
||||
NewPostScreen()
|
||||
}
|
||||
composable(route = "EditModification") {
|
||||
Box(
|
||||
modifier = Modifier.padding(top = 64.dp)
|
||||
) {
|
||||
EditModification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@Composable
|
||||
fun Navigation() {
|
||||
val navController = rememberNavController()
|
||||
SharedTransitionLayout {
|
||||
CompositionLocalProvider(
|
||||
LocalNavController provides navController,
|
||||
LocalSharedTransitionScope provides this@SharedTransitionLayout,
|
||||
) {
|
||||
Box {
|
||||
NavigationController(navController = navController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 用于带导航栏的路由的可复用 composable
|
||||
@Composable
|
||||
@@ -266,204 +159,3 @@ fun ScaffoldWithNavigationBar(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@Composable
|
||||
fun ScaffoldWithNavigationBar2() {
|
||||
val model = IndexViewModel
|
||||
val navigationBarHeight = with(LocalDensity.current) {
|
||||
WindowInsets.navigationBars.getBottom(this).toDp()
|
||||
}
|
||||
val item = listOf(
|
||||
NavigationItem.Home,
|
||||
NavigationItem.Street,
|
||||
NavigationItem.Add,
|
||||
NavigationItem.Message,
|
||||
NavigationItem.Profile
|
||||
)
|
||||
val systemUiController = rememberSystemUiController()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setNavigationBarColor(Color.Black)
|
||||
}
|
||||
Scaffold(
|
||||
bottomBar = {
|
||||
NavigationBar(
|
||||
modifier = Modifier.height(56.dp + navigationBarHeight),
|
||||
containerColor = Color.Black
|
||||
) {
|
||||
item.forEachIndexed { idx, it ->
|
||||
val isSelected = model.tabIndex == idx
|
||||
val iconTint by animateColorAsState(
|
||||
targetValue = if (isSelected) Color.Red else Color.White,
|
||||
animationSpec = tween(durationMillis = 250), label = ""
|
||||
)
|
||||
NavigationBarItem(
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
model.tabIndex = idx
|
||||
// if (it.route == NavigationItem.Add.route || it.route == NavigationItem.Message.route) {
|
||||
// systemUiController.setStatusBarColor(Color.Black, darkIcons = false)
|
||||
// } else {
|
||||
// systemUiController.setStatusBarColor(
|
||||
// Color.Transparent,
|
||||
// darkIcons = true
|
||||
// )
|
||||
// }
|
||||
},
|
||||
colors = NavigationBarItemColors(
|
||||
selectedTextColor = Color.Red,
|
||||
selectedIndicatorColor = Color.Black,
|
||||
unselectedTextColor = Color.Red,
|
||||
disabledIconColor = Color.Red,
|
||||
disabledTextColor = Color.Red,
|
||||
selectedIconColor = iconTint,
|
||||
unselectedIconColor = iconTint,
|
||||
),
|
||||
icon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
imageVector = if (isSelected) it.selectedIcon() else it.icon(),
|
||||
contentDescription = null,
|
||||
tint = iconTint
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
) {
|
||||
when (model.tabIndex) {
|
||||
0 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) {
|
||||
Home()
|
||||
}
|
||||
|
||||
1 -> Street()
|
||||
2 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) { Add() }
|
||||
|
||||
3 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) { Video() }
|
||||
|
||||
4 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) { Profile() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Home() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
PagingBackendSample()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun Street() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
StreetPage()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Add() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Black, darkIcons = false)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
AddPage()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Video() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Black, darkIcons = false)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
ShortVideo()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Message() {
|
||||
val navigationBarHeight = with(LocalDensity.current) {
|
||||
WindowInsets.navigationBars.getBottom(this).toDp()
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
MessagePage()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Profile() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
ProfilePage()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun GreetingPreview() {
|
||||
RiderProTheme {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = Color.White) {
|
||||
Navigation()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
|
||||
data class ListContainer<T>(
|
||||
val total: Int,
|
||||
val page: Int,
|
||||
val pageSize: Int,
|
||||
val list: List<T>
|
||||
)
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.aiosman.riderpro.data.moment
|
||||
|
||||
import android.net.http.HttpException
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.data.ListContainer
|
||||
import com.aiosman.riderpro.model.MomentItem
|
||||
import java.io.IOException
|
||||
|
||||
class MomentPagingSource(
|
||||
private val remoteDataSource: MomentRemoteDataSource,
|
||||
) : PagingSource<Int, MomentItem>() {
|
||||
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentItem> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val moments = remoteDataSource.getMoments(
|
||||
pageNumber = currentPage
|
||||
)
|
||||
|
||||
LoadResult.Page(
|
||||
data = moments.list,
|
||||
prevKey = if (currentPage == 1) null else currentPage - 1,
|
||||
nextKey = if (moments.list.isEmpty()) null else moments.page + 1
|
||||
)
|
||||
} catch (exception: IOException) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, MomentItem>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MomentRemoteDataSource(
|
||||
private val momentService: MomentService,
|
||||
) {
|
||||
suspend fun getMoments(pageNumber: Int): ListContainer<MomentItem> {
|
||||
return momentService.getMoments(pageNumber)
|
||||
}
|
||||
}
|
||||
|
||||
interface MomentService {
|
||||
suspend fun getMoments(pageNumber: Int): ListContainer<MomentItem>
|
||||
}
|
||||
|
||||
class TestMomentServiceImpl() : MomentService {
|
||||
val mockData = (0..300).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
|
||||
)
|
||||
}
|
||||
val testMomentBackend = TestMomentBackend(mockData)
|
||||
override suspend fun getMoments(pageNumber: Int): ListContainer<MomentItem> {
|
||||
return testMomentBackend.fetchMomentItems(pageNumber)
|
||||
}
|
||||
}
|
||||
|
||||
class TestMomentBackend(
|
||||
private val mockData: List<MomentItem>,
|
||||
private val loadDelay: Long = 500,
|
||||
) {
|
||||
val DataBatchSize = 5
|
||||
suspend fun fetchMomentItems(pageNumber: Int): ListContainer<MomentItem> {
|
||||
val from = pageNumber * DataBatchSize
|
||||
val to = (pageNumber + 1) * DataBatchSize
|
||||
val currentSublist = mockData.subList(from, to)
|
||||
// delay
|
||||
kotlinx.coroutines.delay(loadDelay)
|
||||
return ListContainer(
|
||||
total = mockData.size,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = currentSublist
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,16 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.exp
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
//import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
private const val COLOR_TRANSPARENT = 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.model
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.aiosman.riderpro.R
|
||||
|
||||
data class MomentItem(
|
||||
val id: Int,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.test
|
||||
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.test
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.model.MomentItem
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlin.math.ceil
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.test
|
||||
|
||||
data class StreetPosition(
|
||||
val name:String,
|
||||
156
app/src/main/java/com/aiosman/riderpro/ui/Navi.kt
Normal file
156
app/src/main/java/com/aiosman/riderpro/ui/Navi.kt
Normal file
@@ -0,0 +1,156 @@
|
||||
package com.aiosman.riderpro.ui
|
||||
|
||||
import ModificationListScreen
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.SharedTransitionLayout
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import com.aiosman.riderpro.LocalAnimatedContentScope
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.LocalSharedTransitionScope
|
||||
import com.aiosman.riderpro.ui.comment.CommentsScreen
|
||||
import com.aiosman.riderpro.ui.follower.FollowerScreen
|
||||
import com.aiosman.riderpro.ui.gallery.OfficialGalleryScreen
|
||||
import com.aiosman.riderpro.ui.gallery.OfficialPhotographerScreen
|
||||
import com.aiosman.riderpro.ui.gallery.ProfileTimelineScreen
|
||||
import com.aiosman.riderpro.ui.index.IndexScreen
|
||||
import com.aiosman.riderpro.ui.like.LikeScreen
|
||||
import com.aiosman.riderpro.ui.location.LocationDetailScreen
|
||||
import com.aiosman.riderpro.ui.message.NotificationsScreen
|
||||
import com.aiosman.riderpro.ui.modification.EditModificationScreen
|
||||
import com.aiosman.riderpro.ui.post.NewPostScreen
|
||||
import com.aiosman.riderpro.ui.post.PostScreen
|
||||
|
||||
sealed class NavigationRoute(
|
||||
val route: String,
|
||||
) {
|
||||
data object Index : NavigationRoute("Index")
|
||||
data object ProfileTimeline : NavigationRoute("ProfileTimeline")
|
||||
data object LocationDetail : NavigationRoute("LocationDetail/{x}/{y}")
|
||||
data object OfficialPhoto : NavigationRoute("OfficialPhoto")
|
||||
data object OfficialPhotographer : NavigationRoute("OfficialPhotographer")
|
||||
data object Post : NavigationRoute("Post/{id}")
|
||||
data object ModificationList : NavigationRoute("ModificationList")
|
||||
data object MyMessage : NavigationRoute("MyMessage")
|
||||
data object Comments : NavigationRoute("Comments")
|
||||
data object Likes : NavigationRoute("Likes")
|
||||
data object Followers : NavigationRoute("Followers")
|
||||
data object NewPost : NavigationRoute("NewPost")
|
||||
data object EditModification : NavigationRoute("EditModification")
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun NavigationController(navController: NavHostController) {
|
||||
val navigationBarHeight = with(LocalDensity.current) {
|
||||
WindowInsets.navigationBars.getBottom(this).toDp()
|
||||
}
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = NavigationRoute.Index.route,
|
||||
) {
|
||||
composable(route = NavigationRoute.Index.route) {
|
||||
CompositionLocalProvider(
|
||||
LocalAnimatedContentScope provides this,
|
||||
) {
|
||||
IndexScreen()
|
||||
}
|
||||
}
|
||||
composable(route = NavigationRoute.ProfileTimeline.route) {
|
||||
ProfileTimelineScreen()
|
||||
}
|
||||
composable(
|
||||
route = NavigationRoute.LocationDetail.route,
|
||||
arguments = listOf(
|
||||
navArgument("x") { type = NavType.FloatType },
|
||||
navArgument("y") { type = NavType.FloatType }
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.padding(bottom = navigationBarHeight)
|
||||
) {
|
||||
val x = it.arguments?.getFloat("x") ?: 0f
|
||||
val y = it.arguments?.getFloat("y") ?: 0f
|
||||
LocationDetailScreen(
|
||||
x, y
|
||||
)
|
||||
}
|
||||
}
|
||||
composable(route = NavigationRoute.OfficialPhoto.route) {
|
||||
OfficialGalleryScreen()
|
||||
}
|
||||
composable(route = NavigationRoute.OfficialPhotographer.route) {
|
||||
OfficialPhotographerScreen()
|
||||
}
|
||||
composable(
|
||||
route = NavigationRoute.Post.route,
|
||||
arguments = listOf(navArgument("id") { type = NavType.StringType })
|
||||
) { backStackEntry ->
|
||||
CompositionLocalProvider(
|
||||
LocalAnimatedContentScope provides this,
|
||||
) {
|
||||
val id = backStackEntry.arguments?.getString("id")
|
||||
PostScreen(
|
||||
id!!
|
||||
)
|
||||
}
|
||||
}
|
||||
composable(route = NavigationRoute.ModificationList.route) {
|
||||
ModificationListScreen()
|
||||
}
|
||||
composable(route = NavigationRoute.MyMessage.route) {
|
||||
NotificationsScreen()
|
||||
}
|
||||
composable(route = NavigationRoute.Comments.route) {
|
||||
CommentsScreen()
|
||||
}
|
||||
composable(route = NavigationRoute.Likes.route) {
|
||||
LikeScreen()
|
||||
}
|
||||
composable(route = NavigationRoute.Followers.route) {
|
||||
FollowerScreen()
|
||||
}
|
||||
composable(route = NavigationRoute.NewPost.route) {
|
||||
NewPostScreen()
|
||||
}
|
||||
composable(route = NavigationRoute.EditModification.route) {
|
||||
Box(
|
||||
modifier = Modifier.padding(top = 64.dp)
|
||||
) {
|
||||
EditModificationScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@Composable
|
||||
fun Navigation() {
|
||||
val navController = rememberNavController()
|
||||
SharedTransitionLayout {
|
||||
CompositionLocalProvider(
|
||||
LocalNavController provides navController,
|
||||
LocalSharedTransitionScope provides this@SharedTransitionLayout,
|
||||
) {
|
||||
Box {
|
||||
NavigationController(navController = navController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.comment
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -35,6 +35,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.ui.post.CommentsSection
|
||||
import com.aiosman.riderpro.R
|
||||
|
||||
|
||||
@Preview
|
||||
@@ -53,7 +55,7 @@ fun CommentModalContent(onDismiss: () -> Unit = {}) {
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.height(500.dp)
|
||||
modifier = Modifier
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.comment
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -25,6 +25,10 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.aiosman.riderpro.ui.composables
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.SizeTransform
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.animation.with
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun AnimatedCounter(count: Int, modifier: Modifier = Modifier, fontSize: Int = 24) {
|
||||
AnimatedContent(
|
||||
targetState = count,
|
||||
transitionSpec = {
|
||||
// Compare the incoming number with the previous number.
|
||||
if (targetState > initialState) {
|
||||
// If the target number is larger, it slides up and fades in
|
||||
// while the initial (smaller) number slides up and fades out.
|
||||
(slideInVertically { height -> height } + fadeIn()).togetherWith(slideOutVertically { height -> -height } + fadeOut())
|
||||
} else {
|
||||
// If the target number is smaller, it slides down and fades in
|
||||
// while the initial number slides down and fades out.
|
||||
(slideInVertically { height -> -height } + fadeIn()).togetherWith(slideOutVertically { height -> height } + fadeOut())
|
||||
}.using(
|
||||
// Disable clipping since the faded slide-in/out should
|
||||
// be displayed out of bounds.
|
||||
SizeTransform(clip = false)
|
||||
)
|
||||
}
|
||||
) { targetCount ->
|
||||
Text(text = "$targetCount", modifier = modifier, fontSize = fontSize.sp)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.aiosman.riderpro.ui.composables
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.Animatable
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.aiosman.riderpro.R
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun AnimatedLikeIcon(
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: (() -> Unit)? = null
|
||||
) {
|
||||
var liked by remember { mutableStateOf(false) }
|
||||
val animatableRotation = remember { Animatable(0f) }
|
||||
val animatedColor by animateColorAsState(targetValue = if (liked) Color(0xFFd83737) else Color.Black)
|
||||
val scope = rememberCoroutineScope()
|
||||
suspend fun shake() {
|
||||
repeat(2) {
|
||||
animatableRotation.animateTo(
|
||||
targetValue = 10f,
|
||||
animationSpec = tween(100)
|
||||
) {
|
||||
|
||||
}
|
||||
animatableRotation.animateTo(
|
||||
targetValue = -10f,
|
||||
animationSpec = tween(100)
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
animatableRotation.animateTo(
|
||||
targetValue = 0f,
|
||||
animationSpec = tween(100)
|
||||
)
|
||||
}
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.clickable {
|
||||
liked = !liked
|
||||
onClick?.invoke()
|
||||
// Trigger shake animation
|
||||
scope.launch {
|
||||
shake()
|
||||
}
|
||||
|
||||
}) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_like),
|
||||
contentDescription = "Like",
|
||||
modifier = modifier.graphicsLayer {
|
||||
rotationZ = animatableRotation.value
|
||||
},
|
||||
colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(animatedColor)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.composables
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -1,13 +1,11 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.composables
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.areNavigationBarsVisible
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.follower
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -21,10 +21,13 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.comment.NoticeScreenHeader
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun FollowerPage() {
|
||||
fun FollowerScreen() {
|
||||
StatusBarMaskLayout(
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.gallery
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
@@ -44,12 +44,13 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.R
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun GalleryPage() {
|
||||
fun ProfileTimelineScreen() {
|
||||
val pagerState = rememberPagerState(pageCount = { 2 })
|
||||
val scope = rememberCoroutineScope()
|
||||
val systemUiController = rememberSystemUiController()
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.gallery
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -32,10 +32,14 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun OfficialGalleryPage() {
|
||||
fun OfficialGalleryScreen() {
|
||||
StatusBarMaskLayout {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.gallery
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Image
|
||||
@@ -24,7 +24,6 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -38,12 +37,16 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||
|
||||
data class ArtWork(
|
||||
val id: Int,
|
||||
@@ -69,7 +72,7 @@ fun GenerateMockArtWorks(): List<ArtWork> {
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun OfficialPhotographer() {
|
||||
fun OfficialPhotographerScreen() {
|
||||
val lazyListState = rememberLazyListState()
|
||||
var artWorks by remember { mutableStateOf<List<ArtWork>>(emptyList()) }
|
||||
LaunchedEffect(Unit) {
|
||||
@@ -135,7 +138,7 @@ fun OfficialPhotographer() {
|
||||
)
|
||||
)
|
||||
.padding(16.dp)
|
||||
.align(alignment = androidx.compose.ui.Alignment.BottomCenter)
|
||||
.align(alignment = Alignment.BottomCenter)
|
||||
|
||||
) {
|
||||
Column(
|
||||
@@ -257,11 +260,11 @@ fun OfficialPhotographer() {
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_nav_back),
|
||||
colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(Color.White),
|
||||
colorFilter = ColorFilter.tint(Color.White),
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
209
app/src/main/java/com/aiosman/riderpro/ui/index/Index.kt
Normal file
209
app/src/main/java/com/aiosman/riderpro/ui/index/Index.kt
Normal file
@@ -0,0 +1,209 @@
|
||||
package com.aiosman.riderpro.ui.index
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationBarItemColors
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.moment.MomentsList
|
||||
import com.aiosman.riderpro.ui.index.tabs.profile.ProfilePage
|
||||
import com.aiosman.riderpro.ui.index.tabs.shorts.ShortVideo
|
||||
import com.aiosman.riderpro.ui.index.tabs.street.StreetPage
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
@Composable
|
||||
fun IndexScreen() {
|
||||
val model = IndexViewModel
|
||||
val navigationBarHeight = with(LocalDensity.current) {
|
||||
WindowInsets.navigationBars.getBottom(this).toDp()
|
||||
}
|
||||
val item = listOf(
|
||||
NavigationItem.Home,
|
||||
NavigationItem.Street,
|
||||
NavigationItem.Add,
|
||||
NavigationItem.Message,
|
||||
NavigationItem.Profile
|
||||
)
|
||||
val systemUiController = rememberSystemUiController()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setNavigationBarColor(Color.Black)
|
||||
}
|
||||
Scaffold(
|
||||
bottomBar = {
|
||||
NavigationBar(
|
||||
modifier = Modifier.height(56.dp + navigationBarHeight),
|
||||
containerColor = Color.Black
|
||||
) {
|
||||
item.forEachIndexed { idx, it ->
|
||||
val isSelected = model.tabIndex == idx
|
||||
val iconTint by animateColorAsState(
|
||||
targetValue = if (isSelected) Color.Red else Color.White,
|
||||
animationSpec = tween(durationMillis = 250), label = ""
|
||||
)
|
||||
NavigationBarItem(
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
model.tabIndex = idx
|
||||
// if (it.route == NavigationItem.Add.route || it.route == NavigationItem.Message.route) {
|
||||
// systemUiController.setStatusBarColor(Color.Black, darkIcons = false)
|
||||
// } else {
|
||||
// systemUiController.setStatusBarColor(
|
||||
// Color.Transparent,
|
||||
// darkIcons = true
|
||||
// )
|
||||
// }
|
||||
},
|
||||
colors = NavigationBarItemColors(
|
||||
selectedTextColor = Color.Red,
|
||||
selectedIndicatorColor = Color.Black,
|
||||
unselectedTextColor = Color.Red,
|
||||
disabledIconColor = Color.Red,
|
||||
disabledTextColor = Color.Red,
|
||||
selectedIconColor = iconTint,
|
||||
unselectedIconColor = iconTint,
|
||||
),
|
||||
icon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
imageVector = if (isSelected) it.selectedIcon() else it.icon(),
|
||||
contentDescription = null,
|
||||
tint = iconTint
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
) {
|
||||
when (model.tabIndex) {
|
||||
0 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) {
|
||||
Home()
|
||||
}
|
||||
|
||||
1 -> Street()
|
||||
2 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) { Add() }
|
||||
|
||||
3 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) { Video() }
|
||||
|
||||
4 -> Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
) { Profile() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Home() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
MomentsList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun Street() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
StreetPage()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Add() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Black, darkIcons = false)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
AddPage()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Video() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Black, darkIcons = false)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
ShortVideo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun Profile() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
ProfilePage()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -1,13 +1,9 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.filled.Email
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.Place
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import com.aiosman.riderpro.R
|
||||
|
||||
sealed class NavigationItem(
|
||||
val route: String,
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index.tabs.add
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -11,19 +10,19 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.focusModifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.ui.post.NewPostViewModel
|
||||
import com.aiosman.riderpro.R
|
||||
|
||||
@Composable
|
||||
fun AddPage(){
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index.tabs.moment
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
@@ -42,6 +42,15 @@ 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.sp
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.aiosman.riderpro.LocalAnimatedContentScope
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.LocalSharedTransitionScope
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.model.MomentItem
|
||||
import com.aiosman.riderpro.ui.comment.CommentModalContent
|
||||
import com.aiosman.riderpro.ui.composables.AnimatedCounter
|
||||
import com.aiosman.riderpro.ui.composables.AnimatedLikeIcon
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
private val DATA = (0..60).toList().mapIndexed { idx, _ ->
|
||||
@@ -63,41 +72,16 @@ private val DATA = (0..60).toList().mapIndexed { idx, _ ->
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@Composable
|
||||
fun PagingBackendSample() {
|
||||
|
||||
// val myBackend = remember { TestBackend(DATA) }
|
||||
// val pager = remember {
|
||||
// Pager(
|
||||
// PagingConfig(
|
||||
// pageSize = myBackend.DataBatchSize,
|
||||
// enablePlaceholders = true,
|
||||
// maxSize = 200
|
||||
// )
|
||||
// ) {
|
||||
// myBackend.getAllData()
|
||||
// }
|
||||
// }
|
||||
val model = HomeViewModel
|
||||
// val lazyPagingItems = model.pager.collectAsLazyPagingItems()
|
||||
|
||||
fun MomentsList() {
|
||||
val model = MomentViewModel
|
||||
val moments = model.momentsFlow.collectAsLazyPagingItems()
|
||||
LazyColumn {
|
||||
// if (lazyPagingItems.loadState.refresh == LoadState.Loading) {
|
||||
// item {
|
||||
// MomentListLoading()
|
||||
// }
|
||||
// }
|
||||
items(count = model.momentList.size) { index ->
|
||||
val item = model.momentList.getOrNull(index)
|
||||
if (item != null) {
|
||||
MomentCard(item)
|
||||
}
|
||||
items(moments.itemCount) { idx ->
|
||||
val momentItem = moments[idx] ?: return@items
|
||||
MomentCard(momentItem = momentItem)
|
||||
}
|
||||
// if (lazyPagingItems.loadState.append == LoadState.Loading) {
|
||||
// item {
|
||||
// MomentListLoading()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@@ -124,7 +108,7 @@ fun MomentCard(
|
||||
.fillMaxHeight()
|
||||
.weight(1f)
|
||||
ModificationListHeader()
|
||||
MomentBottomOperateRowGroup(momentOperateBtnBoxModifier)
|
||||
MomentBottomOperateRowGroup(momentOperateBtnBoxModifier, momentItem = momentItem)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,9 +296,24 @@ fun MomentOperateBtn(@DrawableRes icon: Int, count: String) {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MomentOperateBtn(count: String, content: @Composable () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
content()
|
||||
AnimatedCounter(
|
||||
count = count.toInt(),
|
||||
fontSize = 14,
|
||||
modifier = Modifier.padding(start = 7.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MomentBottomOperateRowGroup(modifier: Modifier) {
|
||||
fun MomentBottomOperateRowGroup(modifier: Modifier, momentItem: MomentItem) {
|
||||
var systemUiController = rememberSystemUiController()
|
||||
var showCommentModal by remember { mutableStateOf(false) }
|
||||
if (showCommentModal) {
|
||||
@@ -340,7 +339,14 @@ fun MomentBottomOperateRowGroup(modifier: Modifier) {
|
||||
modifier = modifier,
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
MomentOperateBtn(icon = R.drawable.rider_pro_like, count = "21")
|
||||
MomentOperateBtn(count = momentItem.likeCount.toString()) {
|
||||
AnimatedLikeIcon(modifier = Modifier.size(24.dp)) {
|
||||
MomentViewModel.updateById(
|
||||
momentItem.id,
|
||||
momentItem.copy(likeCount = momentItem.likeCount + 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = modifier.clickable(
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.aiosman.riderpro.ui.index.tabs.moment
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.cachedIn
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.data.moment.MomentPagingSource
|
||||
import com.aiosman.riderpro.data.moment.MomentRemoteDataSource
|
||||
import com.aiosman.riderpro.data.moment.TestMomentServiceImpl
|
||||
import com.aiosman.riderpro.model.MomentItem
|
||||
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() {
|
||||
var momentList by mutableStateOf(DATA)
|
||||
|
||||
fun updateById(id: Int, momentItem: MomentItem) {
|
||||
momentList = momentList.map {
|
||||
if (it.id == id) {
|
||||
momentItem
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.toMutableStateList()
|
||||
}
|
||||
|
||||
var momentListPagingSource = MomentPagingSource(
|
||||
MomentRemoteDataSource(TestMomentServiceImpl())
|
||||
|
||||
)
|
||||
|
||||
val momentsFlow: Flow<PagingData<MomentItem>> = Pager(
|
||||
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||
pagingSourceFactory = { momentListPagingSource }
|
||||
).flow
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index.tabs.profile
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
@@ -31,6 +31,10 @@ import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.model.MomentItem
|
||||
import com.aiosman.riderpro.model.profileMomentItems
|
||||
|
||||
|
||||
@Composable
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index.tabs.shorts
|
||||
|
||||
import androidx.compose.animation.core.Animatable
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.draggable
|
||||
import androidx.compose.foundation.gestures.rememberDraggableState
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index.tabs.shorts
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.aiosman.riderpro.ShortViewCompose
|
||||
import com.aiosman.riderpro.ui.theme.RiderProTheme
|
||||
|
||||
val videoUrls = listOf(
|
||||
@@ -1,4 +1,6 @@
|
||||
package com.aiosman.riderpro
|
||||
@file:kotlin.OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.aiosman.riderpro.ui.index.tabs.shorts
|
||||
|
||||
import android.net.Uri
|
||||
import android.view.Gravity
|
||||
@@ -9,6 +11,7 @@ import androidx.annotation.OptIn
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -21,8 +24,11 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -59,22 +65,25 @@ import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||
import androidx.media3.ui.AspectRatioFrameLayout
|
||||
import androidx.media3.ui.PlayerView
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.comment.CommentModalContent
|
||||
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun ShortViewCompose(
|
||||
videoItemsUrl:List<String>,
|
||||
clickItemPosition:Int = 0,
|
||||
videoHeader:@Composable () -> Unit = {},
|
||||
videoBottom:@Composable () -> Unit = {}
|
||||
videoItemsUrl: List<String>,
|
||||
clickItemPosition: Int = 0,
|
||||
videoHeader: @Composable () -> Unit = {},
|
||||
videoBottom: @Composable () -> Unit = {}
|
||||
) {
|
||||
val pagerState: PagerState = run {
|
||||
remember {
|
||||
PagerState(clickItemPosition, 0, videoItemsUrl.size - 1)
|
||||
}
|
||||
}
|
||||
val initialLayout= remember {
|
||||
val initialLayout = remember {
|
||||
mutableStateOf(true)
|
||||
}
|
||||
val pauseIconVisibleState = remember {
|
||||
@@ -85,19 +94,21 @@ fun ShortViewCompose(
|
||||
orientation = Orientation.Vertical,
|
||||
offscreenLimit = 1
|
||||
) {
|
||||
pauseIconVisibleState.value=false
|
||||
SingleVideoItemContent(videoItemsUrl[page],
|
||||
pauseIconVisibleState.value = false
|
||||
SingleVideoItemContent(
|
||||
videoItemsUrl[page],
|
||||
pagerState,
|
||||
page,
|
||||
initialLayout,
|
||||
pauseIconVisibleState,
|
||||
videoHeader,
|
||||
videoBottom)
|
||||
videoBottom
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(clickItemPosition){
|
||||
LaunchedEffect(clickItemPosition) {
|
||||
delay(300)
|
||||
initialLayout.value=false
|
||||
initialLayout.value = false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -112,16 +123,18 @@ private fun SingleVideoItemContent(
|
||||
VideoHeader: @Composable() () -> Unit,
|
||||
VideoBottom: @Composable() () -> Unit,
|
||||
) {
|
||||
Box(modifier = Modifier.fillMaxSize()){
|
||||
VideoPlayer(videoUrl,pagerState,pager,pauseIconVisibleState)
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
VideoPlayer(videoUrl, pagerState, pager, pauseIconVisibleState)
|
||||
VideoHeader.invoke()
|
||||
Box(modifier = Modifier.align(Alignment.BottomStart)){
|
||||
Box(modifier = Modifier.align(Alignment.BottomStart)) {
|
||||
VideoBottom.invoke()
|
||||
}
|
||||
if (initialLayout.value) {
|
||||
Box(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(color = Color.Black))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(color = Color.Black)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,9 +148,12 @@ fun VideoPlayer(
|
||||
pauseIconVisibleState: MutableState<Boolean>,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope= rememberCoroutineScope()
|
||||
val scope = rememberCoroutineScope()
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
var showCommentModal by remember { mutableStateOf(false) }
|
||||
var sheetState = rememberModalBottomSheetState(
|
||||
skipPartiallyExpanded = true
|
||||
)
|
||||
val exoPlayer = remember {
|
||||
ExoPlayer.Builder(context)
|
||||
.build()
|
||||
@@ -160,8 +176,12 @@ fun VideoPlayer(
|
||||
}
|
||||
exoPlayer.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT
|
||||
exoPlayer.repeatMode = Player.REPEAT_MODE_ONE
|
||||
Box(modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.TopCenter) {
|
||||
// player box
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
contentAlignment = Alignment.TopCenter
|
||||
) {
|
||||
var playerView by remember { mutableStateOf<PlayerView?>(null) } // Store reference to PlayerView
|
||||
|
||||
AndroidView(
|
||||
@@ -176,7 +196,8 @@ fun VideoPlayer(
|
||||
hideController()
|
||||
useController = false
|
||||
player = exoPlayer
|
||||
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT // 或 RESIZE_MODE_ZOOM
|
||||
resizeMode =
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT // 或 RESIZE_MODE_ZOOM
|
||||
layoutParams = FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
@@ -226,11 +247,13 @@ fun VideoPlayer(
|
||||
Lifecycle.Event.ON_PAUSE -> {
|
||||
exoPlayer.pause() // 应用进入后台时暂停
|
||||
}
|
||||
|
||||
Lifecycle.Event.ON_RESUME -> {
|
||||
if (pager == pagerState.currentPage) {
|
||||
exoPlayer.play() // 返回前台且为当前页面时恢复播放
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -243,29 +266,58 @@ fun VideoPlayer(
|
||||
|
||||
|
||||
}
|
||||
Box(modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.BottomEnd){
|
||||
Column (modifier = Modifier.padding(bottom = 72.dp, end = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally){
|
||||
// action buttons
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.BottomEnd
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(bottom = 72.dp, end = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
UserAvatar()
|
||||
VideoBtn(icon = R.drawable.rider_pro_video_like, text = "975.9k")
|
||||
VideoBtn(icon = R.drawable.rider_pro_video_comment, text = "1896")
|
||||
VideoBtn(icon = R.drawable.rider_pro_video_comment, text = "1896") {
|
||||
showCommentModal = true
|
||||
}
|
||||
VideoBtn(icon = R.drawable.rider_pro_video_favor, text = "234")
|
||||
VideoBtn(icon = R.drawable.rider_pro_video_share, text = "677k")
|
||||
}
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.BottomStart){
|
||||
Column (modifier = Modifier.padding(start = 16.dp, bottom = 16.dp)){
|
||||
Row (modifier = Modifier.padding(bottom = 8.dp).background(color = Color.Gray),
|
||||
// info
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.BottomStart
|
||||
) {
|
||||
Column(modifier = Modifier.padding(start = 16.dp, bottom = 16.dp)) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp)
|
||||
.background(color = Color.Gray),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
){
|
||||
Image(modifier = Modifier.size(20.dp).padding(start = 4.dp, end = 6.dp), painter = painterResource(id = R.drawable.rider_pro_video_location), contentDescription = "")
|
||||
Text(modifier = Modifier.padding(end = 4.dp),text = "USA",fontSize = 12.sp, color = Color.White, style = TextStyle(fontWeight = FontWeight.Bold))
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.size(20.dp)
|
||||
.padding(start = 4.dp, end = 6.dp),
|
||||
painter = painterResource(id = R.drawable.rider_pro_video_location),
|
||||
contentDescription = ""
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(end = 4.dp),
|
||||
text = "USA",
|
||||
fontSize = 12.sp,
|
||||
color = Color.White,
|
||||
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||
)
|
||||
}
|
||||
Text(text = "@Kevinlinpr",fontSize = 16.sp, color = Color.White, style = TextStyle(fontWeight = FontWeight.Bold))
|
||||
Text(
|
||||
text = "@Kevinlinpr",
|
||||
fontSize = 16.sp,
|
||||
color = Color.White,
|
||||
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -279,23 +331,54 @@ fun VideoPlayer(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showCommentModal) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = { showCommentModal = false },
|
||||
containerColor = Color.White,
|
||||
sheetState = sheetState
|
||||
) {
|
||||
CommentModalContent() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun UserAvatar(){
|
||||
Image(modifier = Modifier.padding(bottom = 16.dp).size(40.dp).border(width = 3.dp, color = Color.White, shape = RoundedCornerShape(40.dp)).clip(
|
||||
RoundedCornerShape(40.dp)
|
||||
), painter = painterResource(id = R.drawable.default_avatar), contentDescription = "")
|
||||
fun UserAvatar() {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 16.dp)
|
||||
.size(40.dp)
|
||||
.border(width = 3.dp, color = Color.White, shape = RoundedCornerShape(40.dp))
|
||||
.clip(
|
||||
RoundedCornerShape(40.dp)
|
||||
), painter = painterResource(id = R.drawable.default_avatar), contentDescription = ""
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun VideoBtn(@DrawableRes icon: Int, text: String){
|
||||
Column (
|
||||
modifier = Modifier.padding(bottom = 16.dp),
|
||||
fun VideoBtn(@DrawableRes icon: Int, text: String, onClick: (() -> Unit)? = null) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 16.dp)
|
||||
.clickable {
|
||||
onClick?.invoke()
|
||||
},
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
){
|
||||
Image(modifier = Modifier.size(36.dp), painter = painterResource(id = icon), contentDescription = "")
|
||||
Text(text = text,fontSize = 11.sp, color = Color.White, style = TextStyle(fontWeight = FontWeight.Bold))
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(36.dp),
|
||||
painter = painterResource(id = icon),
|
||||
contentDescription = ""
|
||||
)
|
||||
Text(
|
||||
text = text,
|
||||
fontSize = 11.sp,
|
||||
color = Color.White,
|
||||
style = TextStyle(fontWeight = FontWeight.Bold)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.index.tabs.street
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
@@ -41,6 +41,10 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.NavOptions
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.test.countries
|
||||
import com.google.android.gms.location.FusedLocationProviderClient
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.android.gms.maps.model.CameraPosition
|
||||
@@ -80,6 +84,7 @@ fun StreetPage() {
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
when (PackageManager.PERMISSION_GRANTED) {
|
||||
ContextCompat.checkSelfPermission(
|
||||
@@ -88,7 +93,7 @@ fun StreetPage() {
|
||||
) -> {
|
||||
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
|
||||
if (location != null) {
|
||||
currentLocation = LatLng(location.latitude, location.longitude)
|
||||
// currentLocation = LatLng(location.latitude, location.longitude)
|
||||
}
|
||||
}
|
||||
hasLocationPermission = true
|
||||
@@ -100,11 +105,20 @@ fun StreetPage() {
|
||||
}
|
||||
}
|
||||
LaunchedEffect(currentLocation) {
|
||||
|
||||
cameraPositionState.position =
|
||||
CameraPosition.fromLatLngZoom(currentLocation ?: LatLng(0.0, 0.0), 10f)
|
||||
CameraPosition.fromLatLngZoom(
|
||||
currentLocation ?: LatLng(
|
||||
countries[0].lat,
|
||||
countries[0].lng
|
||||
), 5f
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize().padding(bottom = 56.dp + navigationBarHeight)
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(bottom = 56.dp + navigationBarHeight)
|
||||
) {
|
||||
GoogleMap(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
@@ -118,14 +132,24 @@ fun StreetPage() {
|
||||
zoomControlsEnabled = false
|
||||
)
|
||||
) {
|
||||
|
||||
// pins
|
||||
countries.forEach { position ->
|
||||
MarkerComposable(
|
||||
state = MarkerState(position = LatLng(position.lat, position.lng)),
|
||||
onClick = { it ->
|
||||
navController.navigate("LocationDetail")
|
||||
onClick = {
|
||||
val screenLocation =
|
||||
cameraPositionState.projection?.toScreenLocation(it.position)
|
||||
val x = screenLocation?.x ?: 0
|
||||
val y = screenLocation?.y ?: 0
|
||||
|
||||
navController.navigate("LocationDetail/${x}/${y}",NavOptions.Builder()
|
||||
.setEnterAnim(0)
|
||||
.setExitAnim(0)
|
||||
.setPopEnterAnim(0)
|
||||
.setPopExitAnim(0)
|
||||
.build())
|
||||
true
|
||||
}
|
||||
},
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_map_mark),
|
||||
@@ -135,19 +159,20 @@ fun StreetPage() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_my_location),
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.padding(start = 16.dp, bottom = 16.dp + navigationBarHeight) .clickable(
|
||||
.padding(start = 16.dp, bottom = 16.dp + navigationBarHeight)
|
||||
.clickable(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
currentLocation?.let {
|
||||
cameraPositionState.position = CameraPosition.fromLatLngZoom(it, cameraPositionState.position.zoom)
|
||||
cameraPositionState.position =
|
||||
CameraPosition.fromLatLngZoom(it, cameraPositionState.position.zoom)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -167,7 +192,8 @@ fun StreetPage() {
|
||||
painter = painterResource(id = R.drawable.rider_pro_new_post_add_pic),
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center).size(36.dp),
|
||||
.align(Alignment.Center)
|
||||
.size(36.dp),
|
||||
colorFilter = ColorFilter.tint(Color.White)
|
||||
|
||||
)
|
||||
@@ -178,10 +204,12 @@ fun StreetPage() {
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.TopCenter)
|
||||
.padding(top = 64.dp, start = 16.dp,end=16.dp)
|
||||
.padding(top = 64.dp, start = 16.dp, end = 16.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.background(Color.White).padding(16.dp),
|
||||
modifier = Modifier
|
||||
.background(Color.White)
|
||||
.padding(16.dp),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@@ -205,7 +233,7 @@ fun StreetPage() {
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
if (searchText.isEmpty()){
|
||||
if (searchText.isEmpty()) {
|
||||
Text(
|
||||
text = "Please enter a search location",
|
||||
color = Color(0xffc6c6c6),
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.like
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -29,10 +29,14 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.comment.NoticeScreenHeader
|
||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LikePage() {
|
||||
fun LikeScreen() {
|
||||
val model = LikePageViewModel
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val listState = rememberLazyListState()
|
||||
@@ -45,10 +49,10 @@ fun LikePage() {
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
model.loader.loadData()
|
||||
LikePageViewModel.loader.loadData()
|
||||
}
|
||||
LaunchedEffect(reachedBottom) {
|
||||
if (reachedBottom) model.loader.loadMore()
|
||||
if (reachedBottom) LikePageViewModel.loader.loadMore()
|
||||
}
|
||||
StatusBarMaskLayout(
|
||||
darkIcons = true,
|
||||
@@ -67,7 +71,7 @@ fun LikePage() {
|
||||
state = listState,
|
||||
|
||||
) {
|
||||
items(model.loader.list, key = { it.id }) {
|
||||
items(LikePageViewModel.loader.list, key = { it.id }) {
|
||||
LikeItem(it)
|
||||
}
|
||||
item {
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.like
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.aiosman.riderpro.test.MockDataContainer
|
||||
import com.aiosman.riderpro.test.MockDataSource
|
||||
import com.aiosman.riderpro.test.MockListContainer
|
||||
|
||||
class LikeDataSource : MockDataSource<LikeItemData>() {
|
||||
init {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.location
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateContentSize
|
||||
@@ -53,12 +53,14 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.R
|
||||
|
||||
data class OfficialGalleryItem(
|
||||
val id: Int,
|
||||
@@ -109,9 +111,8 @@ fun getFeedItems(): List<FeedItem> {
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun LocationDetail() {
|
||||
fun LocationDetailScreen(x: Float, y: Float) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val scaffoldState = rememberBottomSheetScaffoldState(
|
||||
SheetState(
|
||||
@@ -137,6 +138,25 @@ fun LocationDetail() {
|
||||
val peekHeight = (screenHeight * 1 / 3).dp
|
||||
return peekHeight
|
||||
}
|
||||
val view = LocalView.current
|
||||
|
||||
// LaunchedEffect(key1 = Unit) {
|
||||
// val locationOnScreen = IntArray(2).apply {
|
||||
// view.getLocationOnScreen(this)
|
||||
// }
|
||||
// val startX = x - locationOnScreen[0]
|
||||
// val startY = y - locationOnScreen[1]
|
||||
// val radius = hypot(view.width.toDouble(), view.height.toDouble()).toFloat()
|
||||
//
|
||||
// val anim = ViewAnimationUtils.createCircularReveal(view, startX.toInt(), startY.toInt(), 0f, radius).apply {
|
||||
// duration = 600
|
||||
// start()
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
val staggeredGridState = rememberLazyStaggeredGridState()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
@@ -150,7 +170,7 @@ fun LocationDetail() {
|
||||
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
modifier = Modifier.fillMaxSize().background(Color.Transparent)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.default_moment_img),
|
||||
@@ -432,4 +452,5 @@ fun GalleryAndInfo(showGalleryAndInfo: Boolean) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.message
|
||||
|
||||
import android.view.RoundedCorner
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
@@ -8,8 +7,6 @@ import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -18,8 +15,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -29,9 +24,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
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
|
||||
@@ -40,6 +33,10 @@ import androidx.paging.LoadState
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.aiosman.riderpro.ui.index.tabs.moment.MomentListLoading
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.model.ChatNotificationData
|
||||
import com.aiosman.riderpro.model.TestChatBackend
|
||||
|
||||
val chatNotificationData = ChatNotificationData(
|
||||
R.drawable.default_avatar,
|
||||
@@ -49,7 +46,7 @@ val chatNotificationData = ChatNotificationData(
|
||||
6
|
||||
)
|
||||
|
||||
private val ChatData = (0..10).toList().map { chatNotificationData}
|
||||
private val ChatData = (0..10).toList().map { chatNotificationData }
|
||||
|
||||
@Composable
|
||||
fun MessagePage(){
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.message
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -8,12 +8,9 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
@@ -27,12 +24,15 @@ 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.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.modification
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -44,10 +44,14 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.ui.post.NewPostViewModel
|
||||
import com.aiosman.riderpro.ui.comment.NoticeScreenHeader
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.utils.Utils
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun EditModification() {
|
||||
fun EditModificationScreen() {
|
||||
val model = NewPostViewModel
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -62,9 +66,9 @@ fun EditModification() {
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(start = 24.dp, end = 24.dp, top = 16.dp)
|
||||
) {
|
||||
items(model.modificationList) { mod ->
|
||||
items(NewPostViewModel.modificationList) { mod ->
|
||||
AddModificationItem(mod) { updatedMod ->
|
||||
model.modificationList = model.modificationList.map { existingMod ->
|
||||
NewPostViewModel.modificationList = NewPostViewModel.modificationList.map { existingMod ->
|
||||
if (existingMod.key == updatedMod.key) updatedMod else existingMod
|
||||
}.toMutableList()
|
||||
}
|
||||
@@ -72,7 +76,7 @@ fun EditModification() {
|
||||
}
|
||||
item {
|
||||
AddModificationButton {
|
||||
model.modificationList += Modification(
|
||||
NewPostViewModel.modificationList += Modification(
|
||||
key = Utils.generateRandomString(4),
|
||||
name = "",
|
||||
price = "0.0"
|
||||
@@ -17,9 +17,9 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.BottomNavigationPlaceholder
|
||||
import com.aiosman.riderpro.NoticeScreenHeader
|
||||
import com.aiosman.riderpro.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||
import com.aiosman.riderpro.ui.comment.NoticeScreenHeader
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
@Preview
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.modifiers
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.post
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
@@ -43,6 +43,9 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.aiosman.riderpro.LocalNavController
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
|
||||
@@ -62,8 +65,8 @@ fun NewPostScreen() {
|
||||
.fillMaxSize()
|
||||
) {
|
||||
NewPostTopBar()
|
||||
NewPostTextField("Share your adventure…", model.textContent) {
|
||||
model.textContent = it
|
||||
NewPostTextField("Share your adventure…", NewPostViewModel.textContent) {
|
||||
NewPostViewModel.textContent = it
|
||||
}
|
||||
AddImageGrid()
|
||||
AdditionalPostItem()
|
||||
@@ -223,7 +226,7 @@ fun AdditionalPostItem() {
|
||||
}
|
||||
) {
|
||||
isShowLocationModal = false
|
||||
model.searchPlaceAddressResult = it
|
||||
NewPostViewModel.searchPlaceAddressResult = it
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,9 +244,9 @@ fun AdditionalPostItem() {
|
||||
onSelectLocationClick()
|
||||
}
|
||||
) {
|
||||
model.searchPlaceAddressResult?.let {
|
||||
NewPostViewModel.searchPlaceAddressResult?.let {
|
||||
SelectedLocation(it) {
|
||||
model.searchPlaceAddressResult = null
|
||||
NewPostViewModel.searchPlaceAddressResult = null
|
||||
}
|
||||
} ?: Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.post
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.aiosman.riderpro.ui.modification.Modification
|
||||
|
||||
|
||||
object NewPostViewModel : ViewModel() {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.post
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
@@ -56,6 +56,11 @@ import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.LocalAnimatedContentScope
|
||||
import com.aiosman.riderpro.LocalSharedTransitionScope
|
||||
import com.aiosman.riderpro.R
|
||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
fun makeMockImages(): List<PostImage> {
|
||||
@@ -69,7 +74,7 @@ fun makeMockImages(): List<PostImage> {
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@Composable
|
||||
fun PostPage(
|
||||
fun PostScreen(
|
||||
id: String,
|
||||
) {
|
||||
var showCollapseContent by remember { mutableStateOf(true) }
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.ui.post
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Image
|
||||
@@ -33,10 +33,9 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.riderpro.R
|
||||
import com.google.android.gms.common.api.ApiException
|
||||
import com.google.android.libraries.places.api.Places
|
||||
import com.google.android.libraries.places.api.model.Place
|
||||
@@ -49,7 +48,10 @@ data class SearchPlaceAddressResult(
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun SelectLocationModal(onClose:() -> Unit,onSelectedLocation: (SearchPlaceAddressResult) -> Unit) {
|
||||
fun SelectLocationModal(
|
||||
onClose: () -> Unit,
|
||||
onSelectedLocation: (SearchPlaceAddressResult) -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var queryString by remember { mutableStateOf("") }
|
||||
var searchPlaceAddressResults by remember {
|
||||
@@ -94,9 +96,11 @@ fun SelectLocationModal(onClose:() -> Unit,onSelectedLocation: (SearchPlaceAddre
|
||||
)
|
||||
Text(
|
||||
"Cancel",
|
||||
modifier = Modifier.align(Alignment.CenterEnd).clickable {
|
||||
onClose()
|
||||
},
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.clickable {
|
||||
onClose()
|
||||
},
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.aiosman.riderpro
|
||||
package com.aiosman.riderpro.utils
|
||||
|
||||
object Utils {
|
||||
fun generateRandomString(length: Int): String {
|
||||
Reference in New Issue
Block a user