update:add new post

This commit is contained in:
2024-07-15 19:02:42 +08:00
parent 9a9221fa4d
commit 41f66d650a
7 changed files with 203 additions and 42 deletions

View File

@@ -76,4 +76,8 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4) androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest) debugImplementation(libs.androidx.ui.test.manifest)
// coil
implementation("io.coil-kt:coil-compose:2.6.0")
implementation("io.coil-kt:coil:2.6.0")
implementation ("com.google.android.libraries.places:places:3.3.0")
} }

View File

@@ -27,11 +27,11 @@ import androidx.compose.ui.unit.sp
@Preview @Preview
@Composable @Composable
fun FollowerPage() { fun FollowerPage() {
val heightOfStatusBar = 24.dp
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .padding(top = 16.dp + 24.dp, start = 16.dp, end = 16.dp)
.background(color = Color(0xFFFFFFFF))
.padding(16.dp)
) { ) {
NoticeScreenHeader("FOLLOWERS") NoticeScreenHeader("FOLLOWERS")
Spacer(modifier = Modifier.height(28.dp)) Spacer(modifier = Modifier.height(28.dp))

View File

@@ -44,13 +44,16 @@ import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.aiosman.riderpro.ui.theme.RiderProTheme import com.aiosman.riderpro.ui.theme.RiderProTheme
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.google.android.libraries.places.api.Places
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
if (!Places.isInitialized()) {
Places.initialize(applicationContext,"AIzaSyDpgLDH1-SECw_pdjJq_msynq1XrxwgKVI")
}
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
Navigation() Navigation()
@@ -154,7 +157,7 @@ fun NavigationController(navController: NavHostController) {
} }
composable(route = "Followers") { composable(route = "Followers") {
Box( Box(
modifier = Modifier.padding(navigationBarHeight) modifier = Modifier.padding()
) { ) {
FollowerPage() FollowerPage()
} }

View File

@@ -23,6 +23,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview 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 androidx.compose.ui.unit.sp
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R import com.aiosman.riderpro.R
@@ -30,12 +31,15 @@ import com.aiosman.riderpro.R
@Preview @Preview
@Composable @Composable
fun ModificationListScreen() { fun ModificationListScreen() {
val navController = LocalNavController.current
val modifications = getModifications() val modifications = getModifications()
Column(modifier = Modifier.fillMaxSize().background(Color(0xFFF8F8F8))) { Column(modifier = Modifier.fillMaxSize().background(Color(0xFFF8F8F8))) {
TopAppBar( TopAppBar(
title = { Text("Modification List") }, title = { Text("Modification List") },
navigationIcon = { navigationIcon = {
IconButton(onClick = { /* Handle back button click */ }) { IconButton(onClick = {
navController.popBackStack()
}) {
Icon( Icon(
painter = painterResource(id = R.drawable.rider_pro_nav_back), // Replace with your back icon painter = painterResource(id = R.drawable.rider_pro_nav_back), // Replace with your back icon
contentDescription = "Back" contentDescription = "Back"

View File

@@ -1,5 +1,9 @@
package com.aiosman.riderpro package com.aiosman.riderpro
import android.app.Activity
import android.content.Intent
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@@ -32,20 +36,26 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
@Preview @Preview
@Composable @Composable
fun NewPostScreen() { fun NewPostScreen() {
val model = NewPostViewModel
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
) { ) {
NewPostTopBar() NewPostTopBar()
NewPostTextField("What's on your mind?") NewPostTextField("Share your adventure…", model.textContent) {
model.textContent = it
}
AddImageGrid() AddImageGrid()
AdditionalPostItem() AdditionalPostItem()
} }
@@ -53,11 +63,11 @@ fun NewPostScreen() {
@Composable @Composable
fun NewPostTopBar() { fun NewPostTopBar() {
val navController = LocalNavController.current
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 18.dp, vertical = 10.dp) .padding(horizontal = 18.dp, vertical = 10.dp)
) { ) {
Row( Row(
modifier = Modifier.align(Alignment.CenterStart), modifier = Modifier.align(Alignment.CenterStart),
@@ -65,7 +75,9 @@ fun NewPostTopBar() {
Image( Image(
painter = painterResource(id = R.drawable.rider_pro_close), painter = painterResource(id = R.drawable.rider_pro_close),
contentDescription = "Back", contentDescription = "Back",
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp).clickable {
navController.popBackStack()
}
) )
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
Image( Image(
@@ -79,20 +91,19 @@ fun NewPostTopBar() {
} }
@Composable @Composable
fun NewPostTextField(hint: String) { fun NewPostTextField(hint: String, value: String, onValueChange: (String) -> Unit) {
var text by remember { mutableStateOf("") }
Box(modifier = Modifier.fillMaxWidth()) { Box(modifier = Modifier.fillMaxWidth()) {
BasicTextField( BasicTextField(
value = text, value = value,
onValueChange = { text = it }, onValueChange = onValueChange,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.heightIn(200.dp) .heightIn(200.dp)
.padding(horizontal = 18.dp, vertical = 10.dp) .padding(horizontal = 18.dp, vertical = 10.dp)
) )
if (text.isEmpty()) { if (value.isEmpty()) {
Text( Text(
text = hint, text = hint,
color = Color.Gray, color = Color.Gray,
@@ -105,6 +116,18 @@ fun NewPostTextField(hint: String) {
@OptIn(ExperimentalLayoutApi::class) @OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
fun AddImageGrid() { fun AddImageGrid() {
val context = LocalContext.current
var imageUriList by remember { mutableStateOf(listOf<String>()) }
val pickImageLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val uri = result.data?.data
if (uri != null) {
imageUriList = imageUriList + uri.toString()
}
}
}
val stroke = Stroke( val stroke = Stroke(
width = 2f, width = 2f,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f) pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
@@ -119,9 +142,9 @@ fun AddImageGrid() {
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp) horizontalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
repeat(5) { imageUriList.forEach {
Image( AsyncImage(
painter = painterResource(id = R.drawable.rider_pro_moment_demo_1), it,
contentDescription = "Add Image", contentDescription = "Add Image",
modifier = Modifier.size(110.dp), modifier = Modifier.size(110.dp),
contentScale = ContentScale.Crop contentScale = ContentScale.Crop
@@ -133,6 +156,12 @@ fun AddImageGrid() {
.background(Color(0xFFFFFFFF)) .background(Color(0xFFFFFFFF))
.drawBehind { .drawBehind {
drawRoundRect(color = Color(0xFF999999), style = stroke) drawRoundRect(color = Color(0xFF999999), style = stroke)
}
.clickable {
Intent(Intent.ACTION_PICK).apply {
type = "image/*"
pickImageLauncher.launch(this)
}
}, },
) { ) {
Image( Image(
@@ -152,6 +181,7 @@ fun AddImageGrid() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun AdditionalPostItem() { fun AdditionalPostItem() {
val model = NewPostViewModel
val navController = LocalNavController.current val navController = LocalNavController.current
var isShowLocationModal by remember { mutableStateOf(false) } var isShowLocationModal by remember { mutableStateOf(false) }
fun onSelectLocationClick() { fun onSelectLocationClick() {
@@ -164,9 +194,16 @@ fun AdditionalPostItem() {
}, },
containerColor = Color.White containerColor = Color.White
) { ) {
// Sheet content // Sheet content
SelectLocationModal() SelectLocationModal(
onClose = {
isShowLocationModal = false
}
) {
isShowLocationModal = false
model.searchPlaceAddressResult = it
}
} }
} }
Column( Column(
@@ -180,7 +217,11 @@ fun AdditionalPostItem() {
onSelectLocationClick() onSelectLocationClick()
} }
) { ) {
Row( model.searchPlaceAddressResult?.let {
SelectedLocation(it) {
model.searchPlaceAddressResult = null
}
} ?: Row(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Image( Image(
@@ -197,12 +238,12 @@ fun AdditionalPostItem() {
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
} }
} }
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 24.dp).clickable { .padding(vertical = 16.dp, horizontal = 24.dp)
.clickable {
navController.navigate("EditModification") navController.navigate("EditModification")
} }
) { ) {
@@ -224,6 +265,41 @@ fun AdditionalPostItem() {
) )
} }
}
}
}
@Composable
fun SelectedLocation(
searchPlaceAddressResult: SearchPlaceAddressResult,
onRemoveLocation: () -> Unit
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Column(
modifier = Modifier
.weight(1f)
.padding(end = 16.dp)
) {
Text(searchPlaceAddressResult.name, fontWeight = FontWeight.Bold)
Text(searchPlaceAddressResult.address, color = Color(0xFF9a9a9a))
}
Image(
painter = painterResource(id = R.drawable.rider_pro_close),
contentDescription = "Next",
modifier = Modifier
.size(24.dp)
.clickable {
onRemoveLocation()
}
)
} }
} }
} }

View File

@@ -0,0 +1,11 @@
package com.aiosman.riderpro
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
object NewPostViewModel : ViewModel() {
var textContent by mutableStateOf("")
var searchPlaceAddressResult by mutableStateOf<SearchPlaceAddressResult?>(null)
}

View File

@@ -1,7 +1,9 @@
package com.aiosman.riderpro package com.aiosman.riderpro
import android.util.Log
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@@ -24,15 +26,52 @@ 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.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview 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.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
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
import com.google.android.libraries.places.api.net.PlacesClient
import com.google.android.libraries.places.api.net.SearchByTextRequest
data class SearchPlaceAddressResult(
val name: String,
val address: String
)
@Preview
@Composable @Composable
fun SelectLocationModal() { fun SelectLocationModal(onClose:() -> Unit,onSelectedLocation: (SearchPlaceAddressResult) -> Unit) {
val context = LocalContext.current
var queryString by remember { mutableStateOf("") }
var searchPlaceAddressResults by remember {
mutableStateOf<List<SearchPlaceAddressResult>>(
emptyList()
)
}
fun searchAddrWithGoogleMap(query: String) {
val placesClient: PlacesClient = Places.createClient(context)
val placeFields: List<Place.Field> =
listOf(Place.Field.ID, Place.Field.NAME, Place.Field.ADDRESS)
val request = SearchByTextRequest.newInstance(query, placeFields)
placesClient.searchByText(request)
.addOnSuccessListener { response ->
val place = response.places
searchPlaceAddressResults = place.map {
SearchPlaceAddressResult(it.name ?: "", it.address ?: "")
}
}.addOnFailureListener { exception ->
if (exception is ApiException) {
Log.e("SelectLocationModal", "Place not found: ${exception.statusCode}")
}
}
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@@ -51,17 +90,27 @@ fun SelectLocationModal() {
) )
Text( Text(
"Cancel", "Cancel",
modifier = Modifier.align(Alignment.CenterEnd), modifier = Modifier.align(Alignment.CenterEnd).clickable {
onClose()
},
fontSize = 16.sp fontSize = 16.sp
) )
} }
LocationSearchTextInput() LocationSearchTextInput(queryString, onQueryClick = {
searchAddrWithGoogleMap(queryString)
}) {
queryString = it
}
LazyColumn( LazyColumn(
modifier = Modifier.weight(1f).padding(top = 28.dp) modifier = Modifier
.weight(1f)
.padding(top = 28.dp)
) { ) {
item{ item {
repeat(20){ for (searchPlaceAddressResult in searchPlaceAddressResults) {
LocationItem() LocationItem(searchPlaceAddressResult) {
onSelectedLocation(searchPlaceAddressResult)
}
} }
} }
} }
@@ -70,8 +119,11 @@ fun SelectLocationModal() {
} }
@Composable @Composable
fun LocationSearchTextInput() { fun LocationSearchTextInput(
var text by remember { mutableStateOf("") } value: String,
onQueryClick: () -> Unit,
onValueChange: (String) -> Unit
) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -81,17 +133,20 @@ fun LocationSearchTextInput() {
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth().padding(horizontal = 12.dp), .fillMaxWidth()
.padding(horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Image( Image(
painter = painterResource(id = R.drawable.rider_pro_search_location), painter = painterResource(id = R.drawable.rider_pro_search_location),
contentDescription = "Search", contentDescription = "Search",
modifier = Modifier.size(24.dp) modifier = Modifier
.size(24.dp)
.clickable { onQueryClick() }
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
if (text.isEmpty()) { if (value.isEmpty()) {
Text( Text(
"search", "search",
modifier = Modifier.padding(vertical = 16.dp), modifier = Modifier.padding(vertical = 16.dp),
@@ -99,8 +154,8 @@ fun LocationSearchTextInput() {
) )
} }
BasicTextField( BasicTextField(
value = "", value = value,
onValueChange = {}, onValueChange = onValueChange,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 16.dp) .padding(vertical = 16.dp)
@@ -113,20 +168,28 @@ fun LocationSearchTextInput() {
} }
@Composable @Composable
fun LocationItem(){ fun LocationItem(
searchPlaceAddressResult: SearchPlaceAddressResult,
onLocationItemClick: () -> Unit = {}
) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 16.dp) .padding(vertical = 16.dp)
.clickable {
onLocationItemClick()
}
) { ) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Column( Column(
modifier = Modifier.weight(1f).padding(end = 16.dp) modifier = Modifier
.weight(1f)
.padding(end = 16.dp)
) { ) {
Text("Location Name") Text(searchPlaceAddressResult.name, fontWeight = FontWeight.Bold)
Text("Address", color = Color(0xFF9a9a9a)) Text(searchPlaceAddressResult.address, color = Color(0xFF9a9a9a))
} }
Image( Image(
painter = painterResource(id = R.drawable.rider_pro_nav_next), painter = painterResource(id = R.drawable.rider_pro_nav_next),