Merge remote-tracking branch 'refs/remotes/origin/main'
This commit is contained in:
@@ -46,6 +46,7 @@ import java.util.UUID
|
|||||||
@Composable
|
@Composable
|
||||||
fun <T : Any> DraggableGrid(
|
fun <T : Any> DraggableGrid(
|
||||||
items: List<T>,
|
items: List<T>,
|
||||||
|
getItemId: (T) -> String,
|
||||||
onMove: (Int, Int) -> Unit,
|
onMove: (Int, Int) -> Unit,
|
||||||
onDragModeStart: () -> Unit, // New parameter for drag start
|
onDragModeStart: () -> Unit, // New parameter for drag start
|
||||||
onDragModeEnd: () -> Unit, // New parameter for drag end,
|
onDragModeEnd: () -> Unit, // New parameter for drag end,
|
||||||
@@ -66,7 +67,9 @@ fun <T : Any> DraggableGrid(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
|
||||||
) {
|
) {
|
||||||
itemsIndexed(items, key = { _, item -> "${item}-${UUID.randomUUID()}" }) { index, item ->
|
itemsIndexed(items, key = { _, item ->
|
||||||
|
getItemId(item)
|
||||||
|
}) { index, item ->
|
||||||
DraggableItem(dragDropState, index) { isDragging ->
|
DraggableItem(dragDropState, index) { isDragging ->
|
||||||
content(item, isDragging)
|
content(item, isDragging)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.widget.Toast
|
|||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.core.animateDpAsState
|
|
||||||
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
|
||||||
@@ -13,7 +12,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
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.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
@@ -29,7 +27,6 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material.LinearProgressIndicator
|
import androidx.compose.material.LinearProgressIndicator
|
||||||
import androidx.compose.material.MaterialTheme
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -43,7 +40,6 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.drawBehind
|
import androidx.compose.ui.draw.drawBehind
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.graphics.PathEffect
|
import androidx.compose.ui.graphics.PathEffect
|
||||||
@@ -226,7 +222,6 @@ fun NewPostTextField(hint: String, value: String, onValueChange: (String) -> Uni
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AddImageGrid() {
|
fun AddImageGrid() {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
@@ -237,7 +232,12 @@ fun AddImageGrid() {
|
|||||||
contract = ActivityResultContracts.GetMultipleContents()
|
contract = ActivityResultContracts.GetMultipleContents()
|
||||||
) { uris ->
|
) { uris ->
|
||||||
if (uris.isNotEmpty()) {
|
if (uris.isNotEmpty()) {
|
||||||
model.imageUriList += uris.map { it.toString() }
|
model.imageList += uris.map {
|
||||||
|
ImageItem(
|
||||||
|
uri = it.toString(),
|
||||||
|
id = java.util.UUID.randomUUID().toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +245,10 @@ fun AddImageGrid() {
|
|||||||
contract = ActivityResultContracts.TakePicture()
|
contract = ActivityResultContracts.TakePicture()
|
||||||
) { success ->
|
) { success ->
|
||||||
if (success) {
|
if (success) {
|
||||||
model.imageUriList += model.currentPhotoUri.toString()
|
model.imageList += ImageItem(
|
||||||
|
uri = model.currentPhotoUri.toString(),
|
||||||
|
id = java.util.UUID.randomUUID().toString()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,9 +257,9 @@ fun AddImageGrid() {
|
|||||||
pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
|
pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
|
||||||
)
|
)
|
||||||
DraggableGrid(
|
DraggableGrid(
|
||||||
items = NewPostViewModel.imageUriList,
|
items = NewPostViewModel.imageList,
|
||||||
onMove = { from, to ->
|
onMove = { from, to ->
|
||||||
NewPostViewModel.imageUriList = NewPostViewModel.imageUriList.toMutableList().apply {
|
NewPostViewModel.imageList = NewPostViewModel.imageList.toMutableList().apply {
|
||||||
add(to, removeAt(from))
|
add(to, removeAt(from))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -268,14 +271,14 @@ fun AddImageGrid() {
|
|||||||
additionalItems = listOf(
|
additionalItems = listOf(
|
||||||
|
|
||||||
),
|
),
|
||||||
|
getItemId = { it.id }
|
||||||
) { item, isDrag ->
|
) { item, isDrag ->
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
) {
|
) {
|
||||||
CustomAsyncImage(
|
CustomAsyncImage(
|
||||||
LocalContext.current,
|
LocalContext.current,
|
||||||
item,
|
item.uri,
|
||||||
contentDescription = "Image",
|
contentDescription = "Image",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -42,7 +39,7 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
|||||||
@Composable
|
@Composable
|
||||||
fun NewPostImageGridScreen() {
|
fun NewPostImageGridScreen() {
|
||||||
val model = NewPostViewModel
|
val model = NewPostViewModel
|
||||||
val imageList = model.imageUriList
|
val imageList = model.imageList
|
||||||
val pagerState = rememberPagerState(pageCount = { imageList.size })
|
val pagerState = rememberPagerState(pageCount = { imageList.size })
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
val paddingValues = WindowInsets.systemBars.asPaddingValues()
|
val paddingValues = WindowInsets.systemBars.asPaddingValues()
|
||||||
|
|||||||
@@ -19,14 +19,19 @@ import kotlinx.coroutines.withContext
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class ImageItem(
|
||||||
|
val uri: String,
|
||||||
|
val id: String
|
||||||
|
)
|
||||||
|
|
||||||
object NewPostViewModel : ViewModel() {
|
object NewPostViewModel : ViewModel() {
|
||||||
var momentService: MomentService = MomentServiceImpl()
|
var momentService: MomentService = MomentServiceImpl()
|
||||||
var textContent by mutableStateOf("")
|
var textContent by mutableStateOf("")
|
||||||
var searchPlaceAddressResult by mutableStateOf<SearchPlaceAddressResult?>(null)
|
var searchPlaceAddressResult by mutableStateOf<SearchPlaceAddressResult?>(null)
|
||||||
var modificationList by mutableStateOf<List<Modification>>(listOf())
|
var modificationList by mutableStateOf<List<Modification>>(listOf())
|
||||||
var imageUriList by mutableStateOf(listOf<String>())
|
var imageList by mutableStateOf(listOf<ImageItem>())
|
||||||
var relPostId by mutableStateOf<Int?>(null)
|
var relPostId by mutableStateOf<Int?>(null)
|
||||||
var relMoment by mutableStateOf<MomentEntity?>(null)
|
var relMoment by mutableStateOf<MomentEntity?>(null)
|
||||||
var currentPhotoUri: Uri? = null
|
var currentPhotoUri: Uri? = null
|
||||||
@@ -34,14 +39,16 @@ object NewPostViewModel : ViewModel() {
|
|||||||
textContent = ""
|
textContent = ""
|
||||||
searchPlaceAddressResult = null
|
searchPlaceAddressResult = null
|
||||||
modificationList = listOf()
|
modificationList = listOf()
|
||||||
imageUriList = listOf()
|
imageList = listOf()
|
||||||
relPostId = null
|
relPostId = null
|
||||||
}
|
}
|
||||||
fun asNewPostWithImageUris(imageUris: List<String>) {
|
fun asNewPostWithImageUris(imageUris: List<String>) {
|
||||||
textContent = ""
|
textContent = ""
|
||||||
searchPlaceAddressResult = null
|
searchPlaceAddressResult = null
|
||||||
modificationList = listOf()
|
modificationList = listOf()
|
||||||
imageUriList = imageUris
|
imageList = imageUris.map {
|
||||||
|
ImageItem(it, UUID.randomUUID().toString())
|
||||||
|
}
|
||||||
relPostId = null
|
relPostId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +66,7 @@ object NewPostViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun validateMoment(): String? {
|
fun validateMoment(): String? {
|
||||||
if (imageUriList.isEmpty()) {
|
if (imageList.isEmpty()) {
|
||||||
return "Please select at least one image"
|
return "Please select at least one image"
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@@ -67,21 +74,21 @@ object NewPostViewModel : ViewModel() {
|
|||||||
suspend fun createMoment(context: Context, onUploadProgress: (Float) -> Unit) {
|
suspend fun createMoment(context: Context, onUploadProgress: (Float) -> Unit) {
|
||||||
val uploadImageList = emptyList<UploadImage>().toMutableList()
|
val uploadImageList = emptyList<UploadImage>().toMutableList()
|
||||||
var index = 0
|
var index = 0
|
||||||
for (uri in imageUriList) {
|
for (item in imageList) {
|
||||||
val cursor = context.contentResolver.query(Uri.parse(uri), null, null, null, null)
|
val cursor = context.contentResolver.query(Uri.parse(item.uri), null, null, null, null)
|
||||||
cursor?.use {
|
cursor?.use {
|
||||||
if (it.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
val displayName = it.getString(it.getColumnIndex("_display_name"))
|
val displayName = it.getString(it.getColumnIndex("_display_name"))
|
||||||
val extension = displayName.substringAfterLast(".")
|
val extension = displayName.substringAfterLast(".")
|
||||||
Log.d("NewPost", "File name: $displayName, extension: $extension")
|
Log.d("NewPost", "File name: $displayName, extension: $extension")
|
||||||
// read as file
|
// read as file
|
||||||
val file = uriToFile(context, Uri.parse(uri))
|
val file = uriToFile(context, Uri.parse(item.uri))
|
||||||
Log.d("NewPost", "File size: ${file.length()}")
|
Log.d("NewPost", "File size: ${file.length()}")
|
||||||
uploadImageList += UploadImage(file, displayName, uri, extension)
|
uploadImageList += UploadImage(file, displayName, item.uri, extension)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 在上传过程中调用 onUploadProgress 更新进度
|
// 在上传过程中调用 onUploadProgress 更新进度
|
||||||
onUploadProgress(((index / imageUriList.size).toFloat())) // progressValue 是当前上传进度,例如 0.5 表示 50%
|
onUploadProgress(((index / imageList.size).toFloat())) // progressValue 是当前上传进度,例如 0.5 表示 50%
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
momentService.createMoment(textContent, 1, uploadImageList, relPostId)
|
momentService.createMoment(textContent, 1, uploadImageList, relPostId)
|
||||||
@@ -97,7 +104,7 @@ object NewPostViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun deleteImage(index: Int) {
|
fun deleteImage(index: Int) {
|
||||||
imageUriList = imageUriList.toMutableList().apply {
|
imageList = imageList.toMutableList().apply {
|
||||||
removeAt(index)
|
removeAt(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user